libz 0.4__tar.gz → 0.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. {libz-0.4 → libz-0.5}/PKG-INFO +1 -1
  2. {libz-0.4 → libz-0.5}/libz/DLG/prac6.py +119 -119
  3. {libz-0.4 → libz-0.5}/libz/__init__.py +1 -1
  4. {libz-0.4 → libz-0.5}/libz.egg-info/PKG-INFO +1 -1
  5. {libz-0.4 → libz-0.5}/pyproject.toml +1 -1
  6. {libz-0.4 → libz-0.5}/README.md +0 -0
  7. {libz-0.4 → libz-0.5}/libz/AWT/__init__.py +0 -0
  8. {libz-0.4 → libz-0.5}/libz/AWT/prac1.py +0 -0
  9. {libz-0.4 → libz-0.5}/libz/AWT/prac10.py +0 -0
  10. {libz-0.4 → libz-0.5}/libz/AWT/prac2.py +0 -0
  11. {libz-0.4 → libz-0.5}/libz/AWT/prac3.py +0 -0
  12. {libz-0.4 → libz-0.5}/libz/AWT/prac4.py +0 -0
  13. {libz-0.4 → libz-0.5}/libz/AWT/prac5.py +0 -0
  14. {libz-0.4 → libz-0.5}/libz/AWT/prac6.py +0 -0
  15. {libz-0.4 → libz-0.5}/libz/AWT/prac7.py +0 -0
  16. {libz-0.4 → libz-0.5}/libz/AWT/prac8.py +0 -0
  17. {libz-0.4 → libz-0.5}/libz/AWT/prac9.py +0 -0
  18. {libz-0.4 → libz-0.5}/libz/BDA/__init__.py +0 -0
  19. {libz-0.4 → libz-0.5}/libz/BDA/prac1.py +0 -0
  20. {libz-0.4 → libz-0.5}/libz/BDA/prac10.py +0 -0
  21. {libz-0.4 → libz-0.5}/libz/BDA/prac2.py +0 -0
  22. {libz-0.4 → libz-0.5}/libz/BDA/prac3.py +0 -0
  23. {libz-0.4 → libz-0.5}/libz/BDA/prac4.py +0 -0
  24. {libz-0.4 → libz-0.5}/libz/BDA/prac5.py +0 -0
  25. {libz-0.4 → libz-0.5}/libz/BDA/prac6.py +0 -0
  26. {libz-0.4 → libz-0.5}/libz/BDA/prac7.py +0 -0
  27. {libz-0.4 → libz-0.5}/libz/BDA/prac8.py +0 -0
  28. {libz-0.4 → libz-0.5}/libz/BDA/prac9.py +0 -0
  29. {libz-0.4 → libz-0.5}/libz/BIO/__init__.py +0 -0
  30. {libz-0.4 → libz-0.5}/libz/BIO/prac1.py +0 -0
  31. {libz-0.4 → libz-0.5}/libz/BIO/prac10.py +0 -0
  32. {libz-0.4 → libz-0.5}/libz/BIO/prac2.py +0 -0
  33. {libz-0.4 → libz-0.5}/libz/BIO/prac3.py +0 -0
  34. {libz-0.4 → libz-0.5}/libz/BIO/prac4.py +0 -0
  35. {libz-0.4 → libz-0.5}/libz/BIO/prac5.py +0 -0
  36. {libz-0.4 → libz-0.5}/libz/BIO/prac6.py +0 -0
  37. {libz-0.4 → libz-0.5}/libz/BIO/prac7.py +0 -0
  38. {libz-0.4 → libz-0.5}/libz/BIO/prac8.py +0 -0
  39. {libz-0.4 → libz-0.5}/libz/BIO/prac9.py +0 -0
  40. {libz-0.4 → libz-0.5}/libz/DL/__init__.py +0 -0
  41. {libz-0.4 → libz-0.5}/libz/DL/prac1.py +0 -0
  42. {libz-0.4 → libz-0.5}/libz/DL/prac2.py +0 -0
  43. {libz-0.4 → libz-0.5}/libz/DL/prac3.py +0 -0
  44. {libz-0.4 → libz-0.5}/libz/DL/prac4.py +0 -0
  45. {libz-0.4 → libz-0.5}/libz/DL/prac5.py +0 -0
  46. {libz-0.4 → libz-0.5}/libz/DL/prac6.py +0 -0
  47. {libz-0.4 → libz-0.5}/libz/DL/prac7.py +0 -0
  48. {libz-0.4 → libz-0.5}/libz/DL/prac8.py +0 -0
  49. {libz-0.4 → libz-0.5}/libz/DL/prac9.py +0 -0
  50. {libz-0.4 → libz-0.5}/libz/DLG/__init__.py +0 -0
  51. {libz-0.4 → libz-0.5}/libz/DLG/prac1.py +0 -0
  52. {libz-0.4 → libz-0.5}/libz/DLG/prac2.py +0 -0
  53. {libz-0.4 → libz-0.5}/libz/DLG/prac3.py +0 -0
  54. {libz-0.4 → libz-0.5}/libz/DLG/prac4.py +0 -0
  55. {libz-0.4 → libz-0.5}/libz/DLG/prac5.py +0 -0
  56. {libz-0.4 → libz-0.5}/libz/DLG/prac7.py +0 -0
  57. {libz-0.4 → libz-0.5}/libz/DLG/prac8.py +0 -0
  58. {libz-0.4 → libz-0.5}/libz/DLG/prac9.py +0 -0
  59. {libz-0.4 → libz-0.5}/libz/_core.py +0 -0
  60. {libz-0.4 → libz-0.5}/libz.egg-info/SOURCES.txt +0 -0
  61. {libz-0.4 → libz-0.5}/libz.egg-info/dependency_links.txt +0 -0
  62. {libz-0.4 → libz-0.5}/libz.egg-info/top_level.txt +0 -0
  63. {libz-0.4 → libz-0.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: libz
3
- Version: 0.4
3
+ Version: 0.5
4
4
  Summary: A lightweight Python utility toolkit.
5
5
  Requires-Python: >=3.7
6
6
  Description-Content-Type: text/markdown
@@ -1,119 +1,119 @@
1
- # CNN Unsupervised Feature Learning (Exemplar CNN + K-Means) - works with any image folder
2
- # Folder layout: one subfolder per class (class names are used ONLY for evaluation).
3
- # Press Enter to use sklearn's built-in handwritten digits.
4
- import os
5
- import numpy as np
6
- import matplotlib.pyplot as plt
7
- from PIL import Image
8
- from sklearn.cluster import KMeans
9
- from sklearn.metrics import adjusted_rand_score, normalized_mutual_info_score
10
- from tensorflow.keras.models import Model
11
- from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Flatten, Dense
12
-
13
- np.random.seed(42)
14
- IMG_SIZE = 28
15
-
16
- # 1. Load dataset
17
- folder = input("Enter image folder (one subfolder per class) or press Enter for digits: ").strip().strip('"')
18
-
19
- if folder:
20
- class_names = sorted(d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d)))
21
- X, y = [], []
22
- for label, name in enumerate(class_names):
23
- for file in os.listdir(os.path.join(folder, name)):
24
- try:
25
- img = Image.open(os.path.join(folder, name, file)).convert("L")
26
- except OSError:
27
- continue
28
- X.append(np.array(img.resize((IMG_SIZE, IMG_SIZE))))
29
- y.append(label)
30
- X = np.array(X, dtype="float32") / 255.0
31
- y = np.array(y)
32
- else:
33
- from sklearn.datasets import load_digits
34
- digits = load_digits()
35
- X = digits.images.astype("float32") / 16.0
36
- y = digits.target
37
- class_names = [str(i) for i in range(10)]
38
-
39
- X = X[..., np.newaxis] # (samples, height, width, 1)
40
- print("Dataset shape:", X.shape)
41
-
42
- n_clusters = int(input(f"Number of clusters (Enter for {len(class_names)}): ") or len(class_names))
43
-
44
- # 2. Pretext task: exemplar learning
45
- # Each chosen image becomes its own "class"; the CNN learns to recognise
46
- # noisy / shifted views of it, which teaches it useful features without labels.
47
- NUM_EXEMPLARS = min(100, len(X))
48
- VIEWS = 8
49
-
50
- chosen = np.random.choice(len(X), NUM_EXEMPLARS, replace=False)
51
- views, view_labels = [], []
52
- for i, idx in enumerate(chosen):
53
- for v in range(VIEWS):
54
- img = X[idx].copy()
55
- if v > 0:
56
- img = np.roll(img, shift=np.random.randint(-1, 2), axis=np.random.randint(0, 2))
57
- img = np.clip(img + np.random.normal(0, 0.05, img.shape), 0, 1)
58
- views.append(img)
59
- view_labels.append(i)
60
- views = np.array(views, dtype="float32")
61
- view_labels = np.array(view_labels)
62
- print("Exemplar training samples:", len(views))
63
-
64
- # 3. Exemplar CNN
65
- inputs = Input(shape=X.shape[1:])
66
- x = Conv2D(16, 3, activation="relu", padding="same")(inputs)
67
- x = MaxPooling2D()(x)
68
- x = Conv2D(32, 3, activation="relu", padding="same")(x)
69
- x = MaxPooling2D()(x)
70
- x = Flatten()(x)
71
- features = Dense(64, activation="relu", name="features")(x)
72
- outputs = Dense(NUM_EXEMPLARS, activation="softmax")(features)
73
-
74
- exemplar_cnn = Model(inputs, outputs)
75
- exemplar_cnn.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
76
- history = exemplar_cnn.fit(views, view_labels, epochs=15, batch_size=32, shuffle=True, verbose=1)
77
-
78
- # 4. Extract learned features and cluster them
79
- feature_extractor = Model(inputs, features)
80
- learned = feature_extractor.predict(X, verbose=0)
81
- print("Extracted feature shape:", learned.shape)
82
-
83
- clusters = KMeans(n_clusters=n_clusters, n_init=10, random_state=42).fit_predict(learned)
84
- raw_clusters = KMeans(n_clusters=n_clusters, n_init=10, random_state=42).fit_predict(X.reshape(len(X), -1))
85
-
86
- # 5. Evaluate (true labels used only here)
87
- print("\n ARI NMI")
88
- print(f"Raw pixels {adjusted_rand_score(y, raw_clusters):.4f} {normalized_mutual_info_score(y, raw_clusters):.4f}")
89
- print(f"CNN features {adjusted_rand_score(y, clusters):.4f} {normalized_mutual_info_score(y, clusters):.4f}")
90
-
91
- print("\nMost common actual classes in each cluster:")
92
- for c in range(n_clusters):
93
- counts = np.bincount(y[clusters == c], minlength=len(class_names))
94
- top = np.argsort(counts)[::-1][:3]
95
- print(f"Cluster {c}:", [(class_names[t], int(counts[t])) for t in top if counts[t] > 0])
96
-
97
- # 6. Plot pretext loss and sample images from each cluster
98
- plt.figure(figsize=(7, 4))
99
- plt.plot(history.history["loss"], marker="o")
100
- plt.title("Exemplar CNN Training Loss")
101
- plt.xlabel("Epoch")
102
- plt.ylabel("Loss")
103
- plt.grid(True)
104
- plt.show()
105
-
106
- per_row = 6
107
- fig, axes = plt.subplots(n_clusters, per_row, figsize=(per_row, n_clusters))
108
- axes = np.array(axes).reshape(n_clusters, per_row)
109
- for c in range(n_clusters):
110
- members = np.where(clusters == c)[0][:per_row]
111
- for j in range(per_row):
112
- ax = axes[c, j]
113
- ax.axis("off")
114
- if j < len(members):
115
- ax.imshow(X[members[j]].squeeze(), cmap="gray")
116
- axes[c, 0].set_title(f"C{c}", fontsize=8, loc="left")
117
- plt.suptitle("Sample images in each cluster")
118
- plt.tight_layout()
119
- plt.show()
1
+ # CNN Unsupervised Feature Learning (Exemplar CNN + K-Means) - works with any image folder
2
+ # Folder layout: one subfolder per class (class names are used ONLY for evaluation).
3
+ # Press Enter to use sklearn's built-in handwritten digits.
4
+ import os
5
+ import numpy as np
6
+ import matplotlib.pyplot as plt
7
+ from PIL import Image
8
+ from sklearn.cluster import KMeans
9
+ from sklearn.metrics import adjusted_rand_score, normalized_mutual_info_score
10
+ from sklearn.preprocessing import StandardScaler, normalize
11
+ from tensorflow.keras.models import Model
12
+ from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Flatten, Dense
13
+
14
+ np.random.seed(42)
15
+ IMG_SIZE = 28
16
+
17
+ # 1. Load dataset
18
+ folder = input("Enter image folder (one subfolder per class) or press Enter for digits: ").strip().strip('"')
19
+
20
+ if folder:
21
+ class_names = sorted(d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d)))
22
+ X, y = [], []
23
+ for label, name in enumerate(class_names):
24
+ for file in os.listdir(os.path.join(folder, name)):
25
+ try:
26
+ img = Image.open(os.path.join(folder, name, file)).convert("L")
27
+ except OSError:
28
+ continue
29
+ X.append(np.array(img.resize((IMG_SIZE, IMG_SIZE))))
30
+ y.append(label)
31
+ X = np.array(X, dtype="float32") / 255.0
32
+ y = np.array(y)
33
+ else:
34
+ from sklearn.datasets import load_digits
35
+ digits = load_digits()
36
+ X = digits.images.astype("float32") / 16.0
37
+ y = digits.target
38
+ class_names = [str(i) for i in range(10)]
39
+
40
+ X = X[..., np.newaxis] # (samples, height, width, 1)
41
+ print("Dataset shape:", X.shape)
42
+
43
+ n_clusters = int(input(f"Number of clusters (Enter for {len(class_names)}): ") or len(class_names))
44
+
45
+ # 2. Pretext task: exemplar learning
46
+ # Each chosen image becomes its own "class"; the CNN learns to recognise
47
+ # noisy / shifted views of it, which teaches it useful features without labels.
48
+ NUM_EXEMPLARS = min(100, len(X))
49
+ VIEWS = 8
50
+
51
+ chosen = np.random.choice(len(X), NUM_EXEMPLARS, replace=False)
52
+ views, view_labels = [], []
53
+ for i, idx in enumerate(chosen):
54
+ for v in range(VIEWS):
55
+ img = X[idx].copy()
56
+ if v > 0:
57
+ img = np.roll(img, shift=np.random.randint(-1, 2), axis=np.random.randint(0, 2))
58
+ img = np.clip(img + np.random.normal(0, 0.05, img.shape), 0, 1)
59
+ views.append(img)
60
+ view_labels.append(i)
61
+ views = np.array(views, dtype="float32")
62
+ view_labels = np.array(view_labels)
63
+ print("Exemplar training samples:", len(views))
64
+
65
+ # 3. Exemplar CNN
66
+ inputs = Input(shape=X.shape[1:])
67
+ x = Conv2D(16, 3, activation="relu", padding="same")(inputs)
68
+ x = MaxPooling2D()(x)
69
+ x = Conv2D(32, 3, activation="relu", padding="same")(x)
70
+ x = MaxPooling2D()(x)
71
+ x = Flatten()(x)
72
+ features = Dense(64, activation="relu", name="features")(x)
73
+ outputs = Dense(NUM_EXEMPLARS, activation="softmax")(features)
74
+
75
+ exemplar_cnn = Model(inputs, outputs)
76
+ exemplar_cnn.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
77
+ history = exemplar_cnn.fit(views, view_labels, epochs=30, batch_size=32, shuffle=True, verbose=1)
78
+
79
+ # 4. Extract learned features and cluster them
80
+ feature_extractor = Model(inputs, features)
81
+ learned = feature_extractor.predict(X, verbose=0)
82
+ learned = normalize(StandardScaler().fit_transform(learned)) # scale features before clustering
83
+ print("Extracted feature shape:", learned.shape)
84
+
85
+ clusters = KMeans(n_clusters=n_clusters, n_init=10, random_state=42).fit_predict(learned)
86
+
87
+ # 5. Evaluate (true labels used only here)
88
+ print(f"\nAdjusted Rand Index (ARI): {adjusted_rand_score(y, clusters):.4f}")
89
+ print(f"Normalized Mutual Information (NMI): {normalized_mutual_info_score(y, clusters):.4f}")
90
+
91
+ print("\nMost common actual classes in each cluster:")
92
+ for c in range(n_clusters):
93
+ counts = np.bincount(y[clusters == c], minlength=len(class_names))
94
+ top = np.argsort(counts)[::-1][:3]
95
+ print(f"Cluster {c}:", [(class_names[t], int(counts[t])) for t in top if counts[t] > 0])
96
+
97
+ # 6. Plot pretext loss and sample images from each cluster
98
+ plt.figure(figsize=(7, 4))
99
+ plt.plot(history.history["loss"], marker="o")
100
+ plt.title("Exemplar CNN Training Loss")
101
+ plt.xlabel("Epoch")
102
+ plt.ylabel("Loss")
103
+ plt.grid(True)
104
+ plt.show()
105
+
106
+ per_row = 6
107
+ fig, axes = plt.subplots(n_clusters, per_row, figsize=(per_row, n_clusters))
108
+ axes = np.array(axes).reshape(n_clusters, per_row)
109
+ for c in range(n_clusters):
110
+ members = np.where(clusters == c)[0][:per_row]
111
+ for j in range(per_row):
112
+ ax = axes[c, j]
113
+ ax.axis("off")
114
+ if j < len(members):
115
+ ax.imshow(X[members[j]].squeeze(), cmap="gray")
116
+ axes[c, 0].set_title(f"C{c}", fontsize=8, loc="left")
117
+ plt.suptitle("Sample images in each cluster")
118
+ plt.tight_layout()
119
+ plt.show()
@@ -1,5 +1,5 @@
1
1
  """libz - a lightweight Python utility toolkit."""
2
2
  from libz import AWT, DL, DLG, BIO, BDA
3
3
 
4
- __version__ = "0.4"
4
+ __version__ = "0.5"
5
5
  __all__ = ["AWT", "DL", "DLG", "BIO", "BDA"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: libz
3
- Version: 0.4
3
+ Version: 0.5
4
4
  Summary: A lightweight Python utility toolkit.
5
5
  Requires-Python: >=3.7
6
6
  Description-Content-Type: text/markdown
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "libz"
7
- version = "0.4"
7
+ version = "0.5"
8
8
  description = "A lightweight Python utility toolkit."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.7"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes