Skip to content

Commit 6bc5d57

Browse files
committed
add lreg, logireg, mlp, cnn, knn
0 parents  commit 6bc5d57

20 files changed

Lines changed: 4640 additions & 0 deletions

.ipynb_checkpoints/cnn_mnist-checkpoint.ipynb

Lines changed: 643 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 1,
6+
"id": "b4dbce7b-a407-4ba3-b0f7-6a88e8eba0a7",
7+
"metadata": {},
8+
"outputs": [
9+
{
10+
"name": "stdout",
11+
"output_type": "stream",
12+
"text": [
13+
"Path to dataset files: /home/tibless/.cache/kagglehub/datasets/pankrzysiu/cifar10-python/versions/1/cifar-10-batches-py\n"
14+
]
15+
}
16+
],
17+
"source": [
18+
"import kagglehub\n",
19+
"\n",
20+
"# Download CIFAR-10\n",
21+
"path = kagglehub.dataset_download(\"pankrzysiu/cifar10-python\") + '/cifar-10-batches-py'\n",
22+
"\n",
23+
"print(\"Path to dataset files:\", path)"
24+
]
25+
},
26+
{
27+
"cell_type": "code",
28+
"execution_count": 2,
29+
"id": "6ffa7b57-6935-43f6-a4c1-b449fffdc973",
30+
"metadata": {},
31+
"outputs": [
32+
{
33+
"name": "stdout",
34+
"output_type": "stream",
35+
"text": [
36+
"Training data shape: (50000, 32, 32, 3), Training labels shape: (50000,)\n",
37+
"Testing data shape: (10000, 32, 32, 3), Testing labels shape: (10000,)\n"
38+
]
39+
}
40+
],
41+
"source": [
42+
"import os\n",
43+
"import time\n",
44+
"import numpy as np\n",
45+
"\n",
46+
"class2name = [\n",
47+
" 'airplane', # 0\n",
48+
" 'automobile', # 1\n",
49+
" 'bird', # 2\n",
50+
" 'cat', # 3\n",
51+
" 'deer', # 4\n",
52+
" 'dog', # 5\n",
53+
" 'frog', # 6\n",
54+
" 'horse', # 7\n",
55+
" 'ship', # 8\n",
56+
" 'truck' # 9\n",
57+
"]\n",
58+
"\n",
59+
"def unpickle(file):\n",
60+
" import pickle\n",
61+
" with open(file, 'rb') as fo:\n",
62+
" dict = pickle.load(fo, encoding='bytes')\n",
63+
" return dict\n",
64+
"\n",
65+
"def load_cifar10(path):\n",
66+
" x_train = []\n",
67+
" y_train = []\n",
68+
" \n",
69+
" for i in range(1, 6):\n",
70+
" file_path = os.path.join(path, f'data_batch_{i}')\n",
71+
" data_dict = unpickle(file_path)\n",
72+
" \n",
73+
" x_train.append(data_dict[b'data'].reshape(-1, 3, 32, 32).transpose(0, 2, 3, 1))\n",
74+
" y_train += data_dict[b'labels']\n",
75+
" \n",
76+
" x_train = np.vstack(x_train)\n",
77+
" y_train = np.array(y_train)\n",
78+
"\n",
79+
" test_file_path = os.path.join(path, 'test_batch')\n",
80+
" test_dict = unpickle(test_file_path)\n",
81+
" \n",
82+
" x_test = test_dict[b'data'].reshape(-1, 3, 32, 32).transpose(0, 2, 3, 1)\n",
83+
" y_test = np.array(test_dict[b'labels'])\n",
84+
"\n",
85+
" return (x_train, y_train), (x_test, y_test)\n",
86+
"\n",
87+
"(x_train, y_train), (x_test, y_test) = load_cifar10(path)\n",
88+
"\n",
89+
"print(f\"Training data shape: {x_train.shape}, Training labels shape: {y_train.shape}\")\n",
90+
"print(f\"Testing data shape: {x_test.shape}, Testing labels shape: {y_test.shape}\")"
91+
]
92+
},
93+
{
94+
"cell_type": "code",
95+
"execution_count": 3,
96+
"id": "70f04f25-e98d-4d17-a816-4ab61436e533",
97+
"metadata": {},
98+
"outputs": [],
99+
"source": [
100+
"TRAIN = 50000\n",
101+
"TEST = 10000\n",
102+
"x_train = x_train[:TRAIN].reshape(-1, 32 * 32 * 3)\n",
103+
"y_train = y_train[:TRAIN]\n",
104+
"x_test = x_test[:TEST].reshape(-1, 32 * 32 * 3)\n",
105+
"y_test = y_test[:TEST]"
106+
]
107+
},
108+
{
109+
"cell_type": "code",
110+
"execution_count": 4,
111+
"id": "261bd1b5-bbd0-475f-98c5-14048d80a380",
112+
"metadata": {},
113+
"outputs": [
114+
{
115+
"name": "stdout",
116+
"output_type": "stream",
117+
"text": [
118+
"calcu end.\n",
119+
"predict end.\n",
120+
"acc: 0.3386\n",
121+
"time: 0.37079310417175293\n"
122+
]
123+
}
124+
],
125+
"source": [
126+
"import jax.numpy as jnp\n",
127+
"from jax import random, jit, vmap\n",
128+
"\n",
129+
"class KNNClf:\n",
130+
" def __init__(self, k=1, d='euclid', num_class=10, batch_size=(128, 2048)):\n",
131+
" self.k = k\n",
132+
" if k < 1:\n",
133+
" raise ValueError(f'[x] k should be a number >=1, but get {self.k}')\n",
134+
" self.d = d\n",
135+
" self.batch_size = batch_size\n",
136+
" \n",
137+
" # 根据距离度量选择相应的函数\n",
138+
" if d == 'euclid':\n",
139+
" self.distance = self.__euclid_distance\n",
140+
" elif d == 'manhattan':\n",
141+
" self.distance = self.__manhattan_distance\n",
142+
" elif d == 'cosine':\n",
143+
" self.distance = self.__cosine_distances\n",
144+
" elif d == 'chebyshev':\n",
145+
" self.distance = self.__chebyshev_distances\n",
146+
" else:\n",
147+
" print('[!] d should be euclid, manhattan, cosine or chebyshev !')\n",
148+
" print('[!] use default p: euclid')\n",
149+
" self.distance = self.__euclid_distance\n",
150+
"\n",
151+
" self.num_class = 10\n",
152+
" self.training_time = None\n",
153+
" self.testing_time = None\n",
154+
" self.n_k_neighbors = None\n",
155+
"\n",
156+
" @staticmethod\n",
157+
" def __to_jnp(x):\n",
158+
" return jnp.array(x, dtype=jnp.float32)\n",
159+
"\n",
160+
" @staticmethod\n",
161+
" def __euclid_distance(x, y):\n",
162+
" dists = jnp.sqrt(\n",
163+
" jnp.sum(y**2, axis=1, keepdims=True) + jnp.sum(x**2, axis=1) - 2 * jnp.dot(y, x.T)\n",
164+
" )\n",
165+
" return dists\n",
166+
"\n",
167+
" @staticmethod\n",
168+
" def __manhattan_distance(x, y):\n",
169+
" dists = jnp.sum(jnp.abs(y[:, None] - x), axis=2)\n",
170+
" return dists\n",
171+
"\n",
172+
" @staticmethod\n",
173+
" def __chebyshev_distances(x, y):\n",
174+
" dists = jnp.max(jnp.abs(y[:, None] - x), axis=2)\n",
175+
" return dists\n",
176+
"\n",
177+
" @staticmethod\n",
178+
" def __cosine_distances(x, y):\n",
179+
" x_normalized = x / jnp.linalg.norm(x, ord=2, axis=1, keepdims=True)\n",
180+
" y_normalized = y / jnp.linalg.norm(y, ord=2, axis=1, keepdims=True)\n",
181+
" similarity = jnp.dot(y_normalized, x_normalized.T)\n",
182+
" dists = 1 - similarity\n",
183+
" return dists\n",
184+
"\n",
185+
" def fit(self, X_train, y_train):\n",
186+
" start = time.time()\n",
187+
" self.x = self.__to_jnp(X_train)\n",
188+
" self.y = jnp.array(y_train.reshape(-1), dtype=jnp.int32)\n",
189+
" classes, self.static = jnp.unique(self.y, return_counts=True)\n",
190+
" \n",
191+
" if classes[0] != 0:\n",
192+
" raise ValueError('[x] Make sure y is start form 0 !')\n",
193+
"\n",
194+
" self.static = self.static / self.static.sum()\n",
195+
" self.training_time = time.time() - start\n",
196+
"\n",
197+
" \n",
198+
" def predict_proba(self, x_test):\n",
199+
" x_test = self.__to_jnp(x_test)\n",
200+
"\n",
201+
" @jit\n",
202+
" def calculate_proba(n_k_neighbors, y):\n",
203+
" batch_size, k = n_k_neighbors.shape\n",
204+
" neighbor_labels = y[n_k_neighbors.flatten()].reshape(batch_size, k)\n",
205+
" \n",
206+
" def count_labels(labels):\n",
207+
" one_hot = jnp.eye(self.num_class)[labels]\n",
208+
" return jnp.sum(one_hot, axis=0)\n",
209+
" \n",
210+
" counts = vmap(count_labels)(neighbor_labels)\n",
211+
" proba_batch = counts / k\n",
212+
" return proba_batch \n",
213+
"\n",
214+
" start = time.time()\n",
215+
" proba = jnp.zeros((x_test.shape[0], self.static.size))\n",
216+
"\n",
217+
" self.n_k_neighbors = []\n",
218+
" for i in range(0, x_test.shape[0], self.batch_size[0]):\n",
219+
" batch_x_test = x_test[i:i + self.batch_size[0]]\n",
220+
" distance = jnp.zeros((batch_x_test.shape[0], self.x.shape[0]))\n",
221+
"\n",
222+
" for j in range(0, self.x.shape[0], self.batch_size[1]):\n",
223+
" batch_x_train = self.x[j:j + self.batch_size[1]]\n",
224+
" dist_batch = self.distance(batch_x_train, batch_x_test)\n",
225+
" distance = distance.at[:, j:j + dist_batch.shape[1]].set(dist_batch)\n",
226+
"\n",
227+
" n_k_neighbors = jnp.argsort(distance, axis=1)[:, :self.k]\n",
228+
" self.n_k_neighbors.append(n_k_neighbors)\n",
229+
" proba = proba.at[i:i + batch_x_test.shape[0], :].set(calculate_proba(n_k_neighbors, self.y))\n",
230+
" \n",
231+
" self.testing_time = time.time() - start\n",
232+
" \n",
233+
" print('calcu end.')\n",
234+
" n_k_neighbors = jnp.concatenate(self.n_k_neighbors, axis=0)\n",
235+
" self.n_k_neighbors = np.asarray(n_k_neighbors)\n",
236+
" print('predict end.')\n",
237+
" return np.asarray(proba)\n",
238+
"\n",
239+
" def predict(self, x_test):\n",
240+
" proba = self.predict_proba(x_test)\n",
241+
" diff = proba - np.asarray(self.static)\n",
242+
" return np.argmax(diff, axis=1)\n",
243+
"\n",
244+
" def get_testing_time(self):\n",
245+
" return self.testing_time\n",
246+
"\n",
247+
" def get_training_time(self):\n",
248+
" return self.training_time\n",
249+
"\n",
250+
"knn = KNNClf(k=10, num_class=10, d='euclid', batch_size=(x_test.shape[0], x_train.shape[0])) \n",
251+
"knn.fit(x_train, y_train)\n",
252+
"y_pred = knn.predict(x_test)\n",
253+
"print(f'acc: {(y_pred == y_test).mean()}')\n",
254+
"print(f'time: {knn.get_testing_time()}')"
255+
]
256+
}
257+
],
258+
"metadata": {
259+
"kernelspec": {
260+
"display_name": "Python 3 (ipykernel)",
261+
"language": "python",
262+
"name": "python3"
263+
},
264+
"language_info": {
265+
"codemirror_mode": {
266+
"name": "ipython",
267+
"version": 3
268+
},
269+
"file_extension": ".py",
270+
"mimetype": "text/x-python",
271+
"name": "python",
272+
"nbconvert_exporter": "python",
273+
"pygments_lexer": "ipython3",
274+
"version": "3.13.2+"
275+
}
276+
},
277+
"nbformat": 4,
278+
"nbformat_minor": 5
279+
}

0 commit comments

Comments
 (0)