libz 0.3__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.
- {libz-0.3 → libz-0.5}/PKG-INFO +1 -1
- libz-0.5/libz/DL/__init__.py +15 -0
- libz-0.5/libz/DLG/__init__.py +15 -0
- libz-0.5/libz/DLG/prac1.py +71 -0
- libz-0.5/libz/DLG/prac2.py +108 -0
- libz-0.5/libz/DLG/prac3.py +108 -0
- libz-0.5/libz/DLG/prac4.py +105 -0
- libz-0.5/libz/DLG/prac5.py +99 -0
- libz-0.5/libz/DLG/prac6.py +119 -0
- libz-0.5/libz/DLG/prac7.py +110 -0
- libz-0.5/libz/DLG/prac8.py +141 -0
- libz-0.5/libz/DLG/prac9.py +93 -0
- {libz-0.3 → libz-0.5}/libz/__init__.py +1 -1
- {libz-0.3 → libz-0.5}/libz/_core.py +43 -34
- {libz-0.3 → libz-0.5}/libz.egg-info/PKG-INFO +1 -1
- {libz-0.3 → libz-0.5}/pyproject.toml +1 -1
- libz-0.3/libz/DL/__init__.py +0 -3
- libz-0.3/libz/DLG/__init__.py +0 -3
- libz-0.3/libz/DLG/prac1.py +0 -36
- libz-0.3/libz/DLG/prac2.py +0 -3
- libz-0.3/libz/DLG/prac3.py +0 -3
- libz-0.3/libz/DLG/prac4.py +0 -3
- libz-0.3/libz/DLG/prac5.py +0 -3
- libz-0.3/libz/DLG/prac6.py +0 -3
- libz-0.3/libz/DLG/prac7.py +0 -3
- libz-0.3/libz/DLG/prac8.py +0 -3
- libz-0.3/libz/DLG/prac9.py +0 -3
- {libz-0.3 → libz-0.5}/README.md +0 -0
- {libz-0.3 → libz-0.5}/libz/AWT/__init__.py +0 -0
- {libz-0.3 → libz-0.5}/libz/AWT/prac1.py +0 -0
- {libz-0.3 → libz-0.5}/libz/AWT/prac10.py +0 -0
- {libz-0.3 → libz-0.5}/libz/AWT/prac2.py +0 -0
- {libz-0.3 → libz-0.5}/libz/AWT/prac3.py +0 -0
- {libz-0.3 → libz-0.5}/libz/AWT/prac4.py +0 -0
- {libz-0.3 → libz-0.5}/libz/AWT/prac5.py +0 -0
- {libz-0.3 → libz-0.5}/libz/AWT/prac6.py +0 -0
- {libz-0.3 → libz-0.5}/libz/AWT/prac7.py +0 -0
- {libz-0.3 → libz-0.5}/libz/AWT/prac8.py +0 -0
- {libz-0.3 → libz-0.5}/libz/AWT/prac9.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BDA/__init__.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BDA/prac1.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BDA/prac10.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BDA/prac2.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BDA/prac3.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BDA/prac4.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BDA/prac5.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BDA/prac6.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BDA/prac7.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BDA/prac8.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BDA/prac9.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BIO/__init__.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BIO/prac1.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BIO/prac10.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BIO/prac2.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BIO/prac3.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BIO/prac4.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BIO/prac5.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BIO/prac6.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BIO/prac7.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BIO/prac8.py +0 -0
- {libz-0.3 → libz-0.5}/libz/BIO/prac9.py +0 -0
- {libz-0.3 → libz-0.5}/libz/DL/prac1.py +0 -0
- {libz-0.3 → libz-0.5}/libz/DL/prac2.py +0 -0
- {libz-0.3 → libz-0.5}/libz/DL/prac3.py +0 -0
- {libz-0.3 → libz-0.5}/libz/DL/prac4.py +0 -0
- {libz-0.3 → libz-0.5}/libz/DL/prac5.py +0 -0
- {libz-0.3 → libz-0.5}/libz/DL/prac6.py +0 -0
- {libz-0.3 → libz-0.5}/libz/DL/prac7.py +0 -0
- {libz-0.3 → libz-0.5}/libz/DL/prac8.py +0 -0
- {libz-0.3 → libz-0.5}/libz/DL/prac9.py +0 -0
- {libz-0.3 → libz-0.5}/libz.egg-info/SOURCES.txt +0 -0
- {libz-0.3 → libz-0.5}/libz.egg-info/dependency_links.txt +0 -0
- {libz-0.3 → libz-0.5}/libz.egg-info/top_level.txt +0 -0
- {libz-0.3 → libz-0.5}/setup.cfg +0 -0
{libz-0.3 → libz-0.5}/PKG-INFO
RENAMED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from libz._core import register
|
|
2
|
+
|
|
3
|
+
TITLES = {
|
|
4
|
+
1: "Deep feed forward",
|
|
5
|
+
2: "Regularization and optimization",
|
|
6
|
+
3: "Semi-supervised learning",
|
|
7
|
+
4: "Multitasking",
|
|
8
|
+
5: "CNN-based handwriting recognition",
|
|
9
|
+
6: "CNN - unsupervised feature learning",
|
|
10
|
+
7: "Recurrent neural network",
|
|
11
|
+
8: "Recursive neural network (tree)",
|
|
12
|
+
9: "PCA vs linear autoencoder",
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
register(__name__, globals(), TITLES)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from libz._core import register
|
|
2
|
+
|
|
3
|
+
TITLES = {
|
|
4
|
+
1: "Deep feed forward (any CSV)",
|
|
5
|
+
2: "Regularization and optimization (any CSV)",
|
|
6
|
+
3: "Semi-supervised learning (any text CSV)",
|
|
7
|
+
4: "Multitasking (any CSV)",
|
|
8
|
+
5: "CNN-based handwriting recognition (any image folder / MNIST)",
|
|
9
|
+
6: "CNN - unsupervised feature learning (any image folder / digits)",
|
|
10
|
+
7: "Recurrent neural network (any text CSV / IMDB)",
|
|
11
|
+
8: "Recursive neural network (tree) (any text CSV / sample)",
|
|
12
|
+
9: "PCA vs linear autoencoder (any numeric CSV / synthetic)",
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
register(__name__, globals(), TITLES)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Deep Feed Forward Neural Network - works with any CSV classification dataset
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from sklearn.model_selection import train_test_split
|
|
5
|
+
from sklearn.preprocessing import StandardScaler, LabelEncoder
|
|
6
|
+
from sklearn.metrics import classification_report, confusion_matrix
|
|
7
|
+
from tensorflow.keras.models import Sequential
|
|
8
|
+
from tensorflow.keras.layers import Input, Dense, Dropout
|
|
9
|
+
from tensorflow.keras.callbacks import EarlyStopping
|
|
10
|
+
|
|
11
|
+
# 1. Load dataset
|
|
12
|
+
path = input("Enter CSV file path: ").strip().strip('"')
|
|
13
|
+
df = pd.read_csv(path)
|
|
14
|
+
df = df.loc[:, ~df.columns.str.contains("^Unnamed")]
|
|
15
|
+
print(df.head())
|
|
16
|
+
print("Columns:", list(df.columns))
|
|
17
|
+
target = input("Enter target column: ").strip()
|
|
18
|
+
|
|
19
|
+
# 2. Preprocess
|
|
20
|
+
df = df.dropna(subset=[target]).drop_duplicates()
|
|
21
|
+
X = df.drop(columns=[target])
|
|
22
|
+
X = X.drop(columns=[c for c in X.columns if c.lower() == "id"])
|
|
23
|
+
for c in X.columns:
|
|
24
|
+
if pd.api.types.is_numeric_dtype(X[c]):
|
|
25
|
+
X[c] = X[c].fillna(X[c].median())
|
|
26
|
+
else:
|
|
27
|
+
X[c] = X[c].fillna(X[c].mode()[0])
|
|
28
|
+
X = pd.get_dummies(X, drop_first=True, dtype=int)
|
|
29
|
+
|
|
30
|
+
encoder = LabelEncoder()
|
|
31
|
+
y = encoder.fit_transform(df[target].astype(str))
|
|
32
|
+
n_classes = len(encoder.classes_)
|
|
33
|
+
print("Classes:", list(encoder.classes_))
|
|
34
|
+
|
|
35
|
+
# 3. Split and scale
|
|
36
|
+
X_train, X_test, y_train, y_test = train_test_split(
|
|
37
|
+
X, y, test_size=0.2, random_state=42, stratify=y
|
|
38
|
+
)
|
|
39
|
+
scaler = StandardScaler()
|
|
40
|
+
X_train = scaler.fit_transform(X_train)
|
|
41
|
+
X_test = scaler.transform(X_test)
|
|
42
|
+
|
|
43
|
+
# 4. Build deep feed forward network
|
|
44
|
+
model = Sequential([
|
|
45
|
+
Input(shape=(X_train.shape[1],)),
|
|
46
|
+
Dense(128, activation="relu"),
|
|
47
|
+
Dropout(0.3),
|
|
48
|
+
Dense(64, activation="relu"),
|
|
49
|
+
Dropout(0.2),
|
|
50
|
+
Dense(32, activation="relu"),
|
|
51
|
+
Dense(n_classes, activation="softmax"),
|
|
52
|
+
])
|
|
53
|
+
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
|
|
54
|
+
model.summary()
|
|
55
|
+
|
|
56
|
+
# 5. Train
|
|
57
|
+
early_stop = EarlyStopping(monitor="val_loss", patience=5, restore_best_weights=True)
|
|
58
|
+
model.fit(X_train, y_train, epochs=50, batch_size=32,
|
|
59
|
+
validation_split=0.2, callbacks=[early_stop], verbose=1)
|
|
60
|
+
|
|
61
|
+
# 6. Evaluate
|
|
62
|
+
train_acc = model.evaluate(X_train, y_train, verbose=0)[1]
|
|
63
|
+
test_acc = model.evaluate(X_test, y_test, verbose=0)[1]
|
|
64
|
+
y_pred = model.predict(X_test, verbose=0).argmax(axis=1)
|
|
65
|
+
|
|
66
|
+
print(f"\nTraining Accuracy: {train_acc * 100:.2f}%")
|
|
67
|
+
print(f"Testing Accuracy: {test_acc * 100:.2f}%")
|
|
68
|
+
print("\nClassification Report:")
|
|
69
|
+
print(classification_report(y_test, y_pred, target_names=encoder.classes_))
|
|
70
|
+
print("Confusion Matrix:")
|
|
71
|
+
print(confusion_matrix(y_test, y_pred))
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Regularization and Optimization - works with any CSV classification dataset
|
|
2
|
+
# Compares: no regularization vs L2 + Dropout + Early Stopping,
|
|
3
|
+
# and the optimizers Adam, SGD and RMSprop.
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
6
|
+
import matplotlib.pyplot as plt
|
|
7
|
+
from sklearn.model_selection import train_test_split
|
|
8
|
+
from sklearn.preprocessing import StandardScaler, LabelEncoder
|
|
9
|
+
from sklearn.metrics import classification_report, confusion_matrix
|
|
10
|
+
from tensorflow.keras.models import Sequential
|
|
11
|
+
from tensorflow.keras.layers import Input, Dense, Dropout
|
|
12
|
+
from tensorflow.keras.regularizers import l2
|
|
13
|
+
from tensorflow.keras.callbacks import EarlyStopping
|
|
14
|
+
|
|
15
|
+
# 1. Load dataset
|
|
16
|
+
path = input("Enter CSV file path: ").strip().strip('"')
|
|
17
|
+
df = pd.read_csv(path)
|
|
18
|
+
df = df.loc[:, ~df.columns.str.contains("^Unnamed")]
|
|
19
|
+
print(df.head())
|
|
20
|
+
print("Columns:", list(df.columns))
|
|
21
|
+
target = input("Enter target column: ").strip()
|
|
22
|
+
|
|
23
|
+
# 2. Preprocess
|
|
24
|
+
df = df.dropna(subset=[target]).drop_duplicates()
|
|
25
|
+
X = df.drop(columns=[target])
|
|
26
|
+
X = X.drop(columns=[c for c in X.columns if c.lower() == "id"])
|
|
27
|
+
for c in X.columns:
|
|
28
|
+
if pd.api.types.is_numeric_dtype(X[c]):
|
|
29
|
+
X[c] = X[c].fillna(X[c].median())
|
|
30
|
+
else:
|
|
31
|
+
X[c] = X[c].fillna(X[c].mode()[0])
|
|
32
|
+
X = pd.get_dummies(X, drop_first=True, dtype=int)
|
|
33
|
+
|
|
34
|
+
encoder = LabelEncoder()
|
|
35
|
+
y = encoder.fit_transform(df[target].astype(str))
|
|
36
|
+
n_classes = len(encoder.classes_)
|
|
37
|
+
print("Classes:", list(encoder.classes_))
|
|
38
|
+
|
|
39
|
+
X_train, X_test, y_train, y_test = train_test_split(
|
|
40
|
+
X, y, test_size=0.2, random_state=42, stratify=y
|
|
41
|
+
)
|
|
42
|
+
scaler = StandardScaler()
|
|
43
|
+
X_train = scaler.fit_transform(X_train)
|
|
44
|
+
X_test = scaler.transform(X_test)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# 3. Model builder
|
|
48
|
+
def build_model(regularize, optimizer):
|
|
49
|
+
reg = l2(0.001) if regularize else None
|
|
50
|
+
drop = 0.3 if regularize else 0.0
|
|
51
|
+
model = Sequential([
|
|
52
|
+
Input(shape=(X_train.shape[1],)),
|
|
53
|
+
Dense(128, activation="relu", kernel_regularizer=reg),
|
|
54
|
+
Dropout(drop),
|
|
55
|
+
Dense(64, activation="relu", kernel_regularizer=reg),
|
|
56
|
+
Dropout(drop),
|
|
57
|
+
Dense(n_classes, activation="softmax"),
|
|
58
|
+
])
|
|
59
|
+
model.compile(optimizer=optimizer, loss="sparse_categorical_crossentropy", metrics=["accuracy"])
|
|
60
|
+
return model
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# 4. Train every experiment
|
|
64
|
+
experiments = [
|
|
65
|
+
("No regularization (Adam)", False, "adam"),
|
|
66
|
+
("L2 + Dropout + EarlyStop (Adam)", True, "adam"),
|
|
67
|
+
("L2 + Dropout + EarlyStop (SGD)", True, "sgd"),
|
|
68
|
+
("L2 + Dropout + EarlyStop (RMSprop)", True, "rmsprop"),
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
results = []
|
|
72
|
+
histories = {}
|
|
73
|
+
models = {}
|
|
74
|
+
for name, regularize, optimizer in experiments:
|
|
75
|
+
print(f"\nTraining: {name}")
|
|
76
|
+
model = build_model(regularize, optimizer)
|
|
77
|
+
callbacks = [EarlyStopping(monitor="val_loss", patience=5, restore_best_weights=True)] if regularize else []
|
|
78
|
+
history = model.fit(X_train, y_train, epochs=50, batch_size=32,
|
|
79
|
+
validation_split=0.2, callbacks=callbacks, verbose=0)
|
|
80
|
+
train_acc = model.evaluate(X_train, y_train, verbose=0)[1]
|
|
81
|
+
test_acc = model.evaluate(X_test, y_test, verbose=0)[1]
|
|
82
|
+
results.append([name, train_acc * 100, test_acc * 100, len(history.history["loss"])])
|
|
83
|
+
histories[name] = history
|
|
84
|
+
models[name] = model
|
|
85
|
+
|
|
86
|
+
# 5. Compare results
|
|
87
|
+
results_df = pd.DataFrame(results, columns=["Model", "Train Acc", "Test Acc", "Epochs"])
|
|
88
|
+
print("\nComparison:")
|
|
89
|
+
print(results_df.round(2).to_string(index=False))
|
|
90
|
+
|
|
91
|
+
# 6. Plot validation loss of each experiment
|
|
92
|
+
plt.figure(figsize=(9, 5))
|
|
93
|
+
for name, history in histories.items():
|
|
94
|
+
plt.plot(history.history["val_loss"], label=name)
|
|
95
|
+
plt.title("Validation Loss: Regularization and Optimizers")
|
|
96
|
+
plt.xlabel("Epoch")
|
|
97
|
+
plt.ylabel("Validation Loss")
|
|
98
|
+
plt.legend()
|
|
99
|
+
plt.grid(True)
|
|
100
|
+
plt.show()
|
|
101
|
+
|
|
102
|
+
# 7. Detailed report of the best model
|
|
103
|
+
best = results_df.sort_values("Test Acc", ascending=False).iloc[0]["Model"]
|
|
104
|
+
y_pred = models[best].predict(X_test, verbose=0).argmax(axis=1)
|
|
105
|
+
print(f"\nBest model: {best}")
|
|
106
|
+
print(classification_report(y_test, y_pred, target_names=encoder.classes_))
|
|
107
|
+
print("Confusion Matrix:")
|
|
108
|
+
print(confusion_matrix(y_test, y_pred))
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Semi-Supervised Learning (self-training with pseudo-labels) - works with any text CSV
|
|
2
|
+
# Only part of the training data keeps its labels. The model labels the rest itself
|
|
3
|
+
# (only predictions it is confident about) and retrains on the bigger dataset.
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
6
|
+
from sklearn.model_selection import train_test_split
|
|
7
|
+
from sklearn.feature_extraction.text import TfidfVectorizer
|
|
8
|
+
from sklearn.preprocessing import LabelEncoder
|
|
9
|
+
from sklearn.metrics import classification_report, confusion_matrix
|
|
10
|
+
from tensorflow.keras.models import Sequential
|
|
11
|
+
from tensorflow.keras.layers import Input, Dense, Dropout
|
|
12
|
+
from tensorflow.keras.callbacks import EarlyStopping
|
|
13
|
+
|
|
14
|
+
# 1. Load dataset (example: spam.csv -> text column v2, label column v1)
|
|
15
|
+
path = input("Enter CSV file path: ").strip().strip('"')
|
|
16
|
+
try:
|
|
17
|
+
df = pd.read_csv(path)
|
|
18
|
+
except UnicodeDecodeError:
|
|
19
|
+
df = pd.read_csv(path, encoding="latin-1")
|
|
20
|
+
print(df.head())
|
|
21
|
+
print("Columns:", list(df.columns))
|
|
22
|
+
text_col = input("Enter text column: ").strip()
|
|
23
|
+
label_col = input("Enter label column: ").strip()
|
|
24
|
+
labeled_ratio = float(input("Fraction of training data that keeps labels (Enter for 0.3): ") or 0.3)
|
|
25
|
+
|
|
26
|
+
# 2. Clean and encode
|
|
27
|
+
df = df[[text_col, label_col]].dropna().drop_duplicates()
|
|
28
|
+
encoder = LabelEncoder()
|
|
29
|
+
y = encoder.fit_transform(df[label_col].astype(str))
|
|
30
|
+
n_classes = len(encoder.classes_)
|
|
31
|
+
print("Classes:", list(encoder.classes_))
|
|
32
|
+
print(df[label_col].value_counts())
|
|
33
|
+
|
|
34
|
+
X_train_text, X_test_text, y_train, y_test = train_test_split(
|
|
35
|
+
df[text_col].astype(str), y, test_size=0.2, random_state=42, stratify=y
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# 3. TF-IDF features
|
|
39
|
+
vectorizer = TfidfVectorizer(max_features=5000, stop_words="english")
|
|
40
|
+
X_train = vectorizer.fit_transform(X_train_text).toarray().astype("float32")
|
|
41
|
+
X_test = vectorizer.transform(X_test_text).toarray().astype("float32")
|
|
42
|
+
|
|
43
|
+
# 4. Split training data into labelled and unlabelled parts
|
|
44
|
+
X_lab, X_unlab, y_lab, _ = train_test_split(
|
|
45
|
+
X_train, y_train, train_size=labeled_ratio, random_state=42, stratify=y_train
|
|
46
|
+
)
|
|
47
|
+
print("Labelled samples:", len(X_lab))
|
|
48
|
+
print("Unlabelled samples:", len(X_unlab))
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# 5. Model
|
|
52
|
+
def train_model(X, y):
|
|
53
|
+
model = Sequential([
|
|
54
|
+
Input(shape=(X.shape[1],)),
|
|
55
|
+
Dense(64, activation="relu"),
|
|
56
|
+
Dropout(0.3),
|
|
57
|
+
Dense(32, activation="relu"),
|
|
58
|
+
Dropout(0.3),
|
|
59
|
+
Dense(n_classes, activation="softmax"),
|
|
60
|
+
])
|
|
61
|
+
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
|
|
62
|
+
model.fit(X, y, epochs=20, batch_size=32, validation_split=0.2, verbose=0,
|
|
63
|
+
callbacks=[EarlyStopping(monitor="val_loss", patience=3, restore_best_weights=True)])
|
|
64
|
+
return model
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# 6. Baseline: supervised model trained on the labelled part only
|
|
68
|
+
baseline = train_model(X_lab, y_lab)
|
|
69
|
+
baseline_acc = baseline.evaluate(X_test, y_test, verbose=0)[1]
|
|
70
|
+
print(f"\nBaseline (labelled data only) Test Accuracy: {baseline_acc * 100:.2f}%")
|
|
71
|
+
|
|
72
|
+
# 7. Self-training: add confident pseudo-labels and retrain
|
|
73
|
+
threshold = 0.90
|
|
74
|
+
model = baseline
|
|
75
|
+
X_cur, y_cur, pool = X_lab, y_lab, X_unlab
|
|
76
|
+
|
|
77
|
+
for round_no in range(1, 4):
|
|
78
|
+
probs = model.predict(pool, verbose=0)
|
|
79
|
+
confident = probs.max(axis=1) >= threshold
|
|
80
|
+
if confident.sum() == 0:
|
|
81
|
+
print("No more confident predictions.")
|
|
82
|
+
break
|
|
83
|
+
|
|
84
|
+
X_cur = np.vstack([X_cur, pool[confident]])
|
|
85
|
+
y_cur = np.concatenate([y_cur, probs[confident].argmax(axis=1)])
|
|
86
|
+
pool = pool[~confident]
|
|
87
|
+
print(f"Round {round_no}: added {confident.sum()} pseudo-labels "
|
|
88
|
+
f"(training size {len(X_cur)}, {len(pool)} unlabelled left)")
|
|
89
|
+
|
|
90
|
+
model = train_model(X_cur, y_cur)
|
|
91
|
+
|
|
92
|
+
# 8. Compare
|
|
93
|
+
ssl_acc = model.evaluate(X_test, y_test, verbose=0)[1]
|
|
94
|
+
print(f"\nBaseline Test Accuracy: {baseline_acc * 100:.2f}%")
|
|
95
|
+
print(f"Semi-Supervised Test Accuracy: {ssl_acc * 100:.2f}%")
|
|
96
|
+
|
|
97
|
+
if ssl_acc > baseline_acc:
|
|
98
|
+
print("Semi-supervised learning improved the model.")
|
|
99
|
+
elif ssl_acc < baseline_acc:
|
|
100
|
+
print("Baseline model performed better.")
|
|
101
|
+
else:
|
|
102
|
+
print("Both models performed equally.")
|
|
103
|
+
|
|
104
|
+
y_pred = model.predict(X_test, verbose=0).argmax(axis=1)
|
|
105
|
+
print("\nClassification Report (semi-supervised model):")
|
|
106
|
+
print(classification_report(y_test, y_pred, target_names=encoder.classes_))
|
|
107
|
+
print("Confusion Matrix:")
|
|
108
|
+
print(confusion_matrix(y_test, y_pred))
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Multitask Learning - works with any CSV dataset
|
|
2
|
+
# One shared network predicts several target columns at the same time.
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pandas as pd
|
|
5
|
+
import matplotlib.pyplot as plt
|
|
6
|
+
from sklearn.model_selection import train_test_split
|
|
7
|
+
from sklearn.preprocessing import StandardScaler, LabelEncoder
|
|
8
|
+
from sklearn.metrics import accuracy_score, f1_score, confusion_matrix
|
|
9
|
+
from tensorflow.keras.models import Model
|
|
10
|
+
from tensorflow.keras.layers import Input, Dense, Dropout
|
|
11
|
+
|
|
12
|
+
# 1. Load dataset (use sep=";" for files like student-mat.csv)
|
|
13
|
+
path = input("Enter CSV file path: ").strip().strip('"')
|
|
14
|
+
sep = input("Column separator (press Enter for comma): ") or ","
|
|
15
|
+
df = pd.read_csv(path, sep=sep)
|
|
16
|
+
df = df.loc[:, ~df.columns.str.contains("^Unnamed")]
|
|
17
|
+
print(df.head())
|
|
18
|
+
print("Columns:", list(df.columns))
|
|
19
|
+
targets = [t.strip() for t in input("Enter 2 or more target columns (comma separated): ").split(",")]
|
|
20
|
+
|
|
21
|
+
# 2. Create one label per task
|
|
22
|
+
df = df.dropna(subset=targets).drop_duplicates()
|
|
23
|
+
Y = []
|
|
24
|
+
encoders = []
|
|
25
|
+
for t in targets:
|
|
26
|
+
col = df[t]
|
|
27
|
+
# Numeric column with many values -> High / Low (split at median)
|
|
28
|
+
if pd.api.types.is_numeric_dtype(col) and col.nunique() > 10:
|
|
29
|
+
col = np.where(col >= col.median(), "High", "Low")
|
|
30
|
+
enc = LabelEncoder()
|
|
31
|
+
Y.append(enc.fit_transform(pd.Series(col).astype(str)))
|
|
32
|
+
encoders.append(enc)
|
|
33
|
+
print(f"{t} classes:", list(enc.classes_))
|
|
34
|
+
|
|
35
|
+
# 3. Prepare input features
|
|
36
|
+
X = df.drop(columns=targets)
|
|
37
|
+
X = X.drop(columns=[c for c in X.columns if c.lower() == "id"])
|
|
38
|
+
for c in X.columns:
|
|
39
|
+
if pd.api.types.is_numeric_dtype(X[c]):
|
|
40
|
+
X[c] = X[c].fillna(X[c].median())
|
|
41
|
+
else:
|
|
42
|
+
X[c] = X[c].fillna(X[c].mode()[0])
|
|
43
|
+
X = pd.get_dummies(X, drop_first=True, dtype=int).values
|
|
44
|
+
|
|
45
|
+
train_idx, test_idx = train_test_split(np.arange(len(X)), test_size=0.2, random_state=42)
|
|
46
|
+
scaler = StandardScaler()
|
|
47
|
+
X_train = scaler.fit_transform(X[train_idx])
|
|
48
|
+
X_test = scaler.transform(X[test_idx])
|
|
49
|
+
Y_train = [y[train_idx] for y in Y]
|
|
50
|
+
Y_test = [y[test_idx] for y in Y]
|
|
51
|
+
|
|
52
|
+
# 4. Build multitask network: shared layers + one output head per task
|
|
53
|
+
inputs = Input(shape=(X_train.shape[1],))
|
|
54
|
+
shared = Dense(64, activation="relu")(inputs)
|
|
55
|
+
shared = Dropout(0.2)(shared)
|
|
56
|
+
shared = Dense(32, activation="relu")(shared)
|
|
57
|
+
outputs = [
|
|
58
|
+
Dense(len(enc.classes_), activation="softmax", name=f"task{i + 1}")(shared)
|
|
59
|
+
for i, enc in enumerate(encoders)
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
model = Model(inputs, outputs)
|
|
63
|
+
model.compile(
|
|
64
|
+
optimizer="adam",
|
|
65
|
+
loss=["sparse_categorical_crossentropy"] * len(targets),
|
|
66
|
+
metrics=[["accuracy"]] * len(targets),
|
|
67
|
+
)
|
|
68
|
+
model.summary()
|
|
69
|
+
|
|
70
|
+
# 5. Train
|
|
71
|
+
history = model.fit(X_train, Y_train, epochs=100, batch_size=32,
|
|
72
|
+
validation_split=0.2, verbose=0)
|
|
73
|
+
|
|
74
|
+
plt.figure(figsize=(8, 5))
|
|
75
|
+
plt.plot(history.history["loss"], label="Training Loss")
|
|
76
|
+
plt.plot(history.history["val_loss"], label="Validation Loss")
|
|
77
|
+
plt.title("Multitask Training Loss")
|
|
78
|
+
plt.xlabel("Epoch")
|
|
79
|
+
plt.ylabel("Total Loss")
|
|
80
|
+
plt.legend()
|
|
81
|
+
plt.grid(True)
|
|
82
|
+
plt.show()
|
|
83
|
+
|
|
84
|
+
# 6. Evaluate every task
|
|
85
|
+
preds = model.predict(X_test, verbose=0)
|
|
86
|
+
if len(targets) == 1:
|
|
87
|
+
preds = [preds]
|
|
88
|
+
|
|
89
|
+
results = []
|
|
90
|
+
for i, t in enumerate(targets):
|
|
91
|
+
y_pred = preds[i].argmax(axis=1)
|
|
92
|
+
acc = accuracy_score(Y_test[i], y_pred)
|
|
93
|
+
f1 = f1_score(Y_test[i], y_pred, average="weighted", zero_division=0)
|
|
94
|
+
results.append([t, acc * 100, f1 * 100])
|
|
95
|
+
print(f"\n{t} Confusion Matrix:")
|
|
96
|
+
print(confusion_matrix(Y_test[i], y_pred))
|
|
97
|
+
|
|
98
|
+
print("\nTask-wise Evaluation:")
|
|
99
|
+
print(pd.DataFrame(results, columns=["Task", "Accuracy", "F1 Score"]).round(2).to_string(index=False))
|
|
100
|
+
|
|
101
|
+
# 7. Predict all tasks for one sample
|
|
102
|
+
print("\nSample prediction (first test row):")
|
|
103
|
+
for i, t in enumerate(targets):
|
|
104
|
+
p = preds[i][0]
|
|
105
|
+
print(f"{t}: {encoders[i].classes_[p.argmax()]} (probability {p.max():.4f})")
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# CNN-Based Handwriting Recognition - works with any folder of handwriting images
|
|
2
|
+
# Folder layout: one subfolder per class, e.g. data/A/*.png, data/B/*.png ...
|
|
3
|
+
# Press Enter to use the built-in MNIST handwritten digits.
|
|
4
|
+
import os
|
|
5
|
+
import numpy as np
|
|
6
|
+
import matplotlib.pyplot as plt
|
|
7
|
+
from PIL import Image
|
|
8
|
+
from sklearn.model_selection import train_test_split
|
|
9
|
+
from sklearn.metrics import classification_report, confusion_matrix
|
|
10
|
+
from tensorflow.keras.models import Sequential
|
|
11
|
+
from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Flatten, Dense, Dropout
|
|
12
|
+
from tensorflow.keras.callbacks import EarlyStopping
|
|
13
|
+
|
|
14
|
+
IMG_SIZE = 28
|
|
15
|
+
|
|
16
|
+
# 1. Load dataset
|
|
17
|
+
folder = input("Enter image folder (one subfolder per class) or press Enter for MNIST: ").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 # skip files that are not images
|
|
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
|
+
# Scanned handwriting is dark ink on white paper: invert so ink is bright (like MNIST)
|
|
33
|
+
if X.mean() > 0.5:
|
|
34
|
+
X = 1.0 - X
|
|
35
|
+
X_train, X_test, y_train, y_test = train_test_split(
|
|
36
|
+
X, y, test_size=0.2, random_state=42, stratify=y
|
|
37
|
+
)
|
|
38
|
+
else:
|
|
39
|
+
from tensorflow.keras.datasets import mnist
|
|
40
|
+
(X_train, y_train), (X_test, y_test) = mnist.load_data()
|
|
41
|
+
X_train = X_train.astype("float32") / 255.0
|
|
42
|
+
X_test = X_test.astype("float32") / 255.0
|
|
43
|
+
class_names = [str(i) for i in range(10)]
|
|
44
|
+
|
|
45
|
+
# Add channel dimension: (samples, height, width, 1)
|
|
46
|
+
X_train = X_train[..., np.newaxis]
|
|
47
|
+
X_test = X_test[..., np.newaxis]
|
|
48
|
+
n_classes = len(class_names)
|
|
49
|
+
print("Classes:", class_names)
|
|
50
|
+
print("Training images:", X_train.shape, "Testing images:", X_test.shape)
|
|
51
|
+
|
|
52
|
+
# 2. Build CNN
|
|
53
|
+
model = Sequential([
|
|
54
|
+
Input(shape=(IMG_SIZE, IMG_SIZE, 1)),
|
|
55
|
+
Conv2D(32, 3, activation="relu", padding="same"),
|
|
56
|
+
MaxPooling2D(),
|
|
57
|
+
Conv2D(64, 3, activation="relu", padding="same"),
|
|
58
|
+
MaxPooling2D(),
|
|
59
|
+
Flatten(),
|
|
60
|
+
Dense(128, activation="relu"),
|
|
61
|
+
Dropout(0.3),
|
|
62
|
+
Dense(n_classes, activation="softmax"),
|
|
63
|
+
])
|
|
64
|
+
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
|
|
65
|
+
model.summary()
|
|
66
|
+
|
|
67
|
+
# 3. Train
|
|
68
|
+
history = model.fit(
|
|
69
|
+
X_train, y_train, epochs=10, batch_size=64, validation_split=0.1,
|
|
70
|
+
callbacks=[EarlyStopping(monitor="val_loss", patience=3, restore_best_weights=True)],
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
plt.figure(figsize=(8, 5))
|
|
74
|
+
plt.plot(history.history["accuracy"], label="Training Accuracy")
|
|
75
|
+
plt.plot(history.history["val_accuracy"], label="Validation Accuracy")
|
|
76
|
+
plt.title("CNN Handwriting Recognition Accuracy")
|
|
77
|
+
plt.xlabel("Epoch")
|
|
78
|
+
plt.ylabel("Accuracy")
|
|
79
|
+
plt.legend()
|
|
80
|
+
plt.grid(True)
|
|
81
|
+
plt.show()
|
|
82
|
+
|
|
83
|
+
# 4. Evaluate
|
|
84
|
+
test_loss, test_acc = model.evaluate(X_test, y_test, verbose=0)
|
|
85
|
+
y_pred = model.predict(X_test, verbose=0).argmax(axis=1)
|
|
86
|
+
print(f"\nTest Accuracy: {test_acc * 100:.2f}%")
|
|
87
|
+
print(classification_report(y_test, y_pred, target_names=class_names))
|
|
88
|
+
print("Confusion Matrix:")
|
|
89
|
+
print(confusion_matrix(y_test, y_pred))
|
|
90
|
+
|
|
91
|
+
# 5. Show some test images with predictions
|
|
92
|
+
plt.figure(figsize=(12, 3))
|
|
93
|
+
for i in range(min(8, len(X_test))):
|
|
94
|
+
plt.subplot(1, 8, i + 1)
|
|
95
|
+
plt.imshow(X_test[i].squeeze(), cmap="gray")
|
|
96
|
+
plt.title(f"Pred: {class_names[y_pred[i]]}\nTrue: {class_names[y_test[i]]}")
|
|
97
|
+
plt.axis("off")
|
|
98
|
+
plt.tight_layout()
|
|
99
|
+
plt.show()
|
|
@@ -0,0 +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 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()
|