From c1e53022d751d8f32050c3e3d813849c161eb1a3 Mon Sep 17 00:00:00 2001 From: Myla <myla.arab@ecl19.ec-lyon.fr> Date: Wed, 2 Nov 2022 19:38:28 +0100 Subject: [PATCH] first commit --- .gitignore | 1 + __pycache__/read_cifar.cpython-37.pyc | Bin 0 -> 1493 bytes knn.py | 63 +++++++ mlp.py | 254 ++++++++++++++++++++++++++ read_cifar.py | 49 +++++ 5 files changed, 367 insertions(+) create mode 100644 .gitignore create mode 100644 __pycache__/read_cifar.cpython-37.pyc create mode 100644 knn.py create mode 100644 mlp.py create mode 100644 read_cifar.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1269488 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +data diff --git a/__pycache__/read_cifar.cpython-37.pyc b/__pycache__/read_cifar.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b48dc30065475775d3fe048e26ff3ba78fcc652d GIT binary patch literal 1493 zcmZ?b<>g{vU|=}EEGapOm4V?ghy%kc3=9ko3=9m#Aq)%*DGVu$ISf%Cnkk1dmnn*g z5yWQ9VUA)3%dteUrn03nrLtzRgK!#?Btr`G9HtbO6xJ4&D2^1i6!sQ|D9#j)6wVfg zD6SO7U<OUDmms_RG#PKPhLjfMq-rwVVkt;0$+*Q<lv+|+l$Xp1l4oFGU}a!n;ACK6 zaE3XjgrSBZg|V5bU!<0?gfWY$hB1XHg}IlhmMNSeg&~k3h#`WZggJ|)hAD+b62xLn zVeMtAWrm8efyLOsVk|YxH7sdN!3>)0ez%y4l5VjkRhFa{Yck&ANX<*mPsz+nF9rog zN@7VO$fYSIl?AEAYzzzxIf+TBImMdnw^;HEQuA)H6=Wu7=cL|Z$;nSlxy6)MaEmpu zs3@`W7JFJweqxES(Jj`@yb?1LP1Yi21_p*(ENPh_)hU_DCAU~Wrr%<Nn7ERmNQ8lb z;a97(RZM7cYEf}aZe>nlVvI|Ea%paAUP*C`tFuqMk%5s>jIX~72*(?k#GA!C78Dev z=9Od?7bm8t#upUjr{(9R#CztIq~_#grl;m5r^Y)Lm1L%6CTFJR<fO)gxERJ{<|d}6 z>L%wT78ipg5=%1k^J0op6I0@oGt&}_^a?6(2_U%fNr@%N862Qk0H+&99!3d95k?WF zA~6OA26%LVq6!p1;OIKSz`#(#kj0n|BAHScdzoq(;e2K=pQ$3Fgas6V%}g!~u~D_m zC9GL&3)pKIQdnx3(-_4V7BbbclyKCrG&9C9)w0&Il`t&etYKWpn8KRPRFqZ2TEoV~ zP|H}$RH#$Juz;(Ev4%B`X(1!Xo&{VrOf_s^9#f%CI70~s+-$amOknfaYdN60*um-; z!91oK4ls|YhOveTnmjZai$H#V2}+hPK_0B)1;raARN_@ria-*#xJpusOCVyJ+(kSL z3=BoQAc7A>@PlHWwJ0$!J@pn-elav9WaVe(frIcCOL1mZ>Mic%{JiAElGMD!l2lDj zu%aR%kal5^cE+Szte~`0e2X#S7GvZsPOu|Dw%+1~q@Z{Z2b_o?geXWG7a|@(W)(|; zG8dx&7>Y3RF!C|-F!3=8F^VzrG4e4Lse)n@lu$v+Krsr+gy0yhgU09rrV@q)%ry)P z85c6vGS@KFFiSGjFoH-XhFXSN#u~W12tzGP4MPe;2@5C=TbU#oYFTR-QTS{%P}vj) zusnMWBSbZn&jE_%8ul8FG?rinO-4UWR&dbXVk=6_OUci@#a)nElv`Q?PQXR7ApbIF z=9Or2B83}kaY0UI$t}k0TkPNv%S*b&1!j~KC1&Q`;(>)7h*zWx3T_n;0m_R=!N?0X zB_5=)IJE>6O2q=8AYv3^6k_6If`q34Q;{A61A``a5h$PBVk@aE$jnPGVgi{b4RRc7 zUTJPYCBzHN#U(|z*z;1rr3E+{fCC?F0>ol8Cve#0=BJeAq}qYfTQMkwaWL{QaxikR J$Z&B80{{_uZ@>Tm literal 0 HcmV?d00001 diff --git a/knn.py b/knn.py new file mode 100644 index 0000000..90154a7 --- /dev/null +++ b/knn.py @@ -0,0 +1,63 @@ +import numpy as np +import matplotlib.pyplot as plt +from math import * +import read_cifar + + + +def distance_matrix(A,B): + k1 = np.sum(A**2, axis=1)[:,np.newaxis] + k2 = np.sum(B**2, axis=1) + k3 = -2*np.dot(A,B.T) + dists = np.round(np.sqrt(k1+k2+k3),2) + return dists + + + +def knn_predict(dists,labels_train,k): + # prediction du label pour le test + # l'ensemble de référence est l'ensemble d'apprentissage + num_test = dists.shape[0] + labels_predict = np.zeros(num_test) + for i in range(num_test): + L = [] + # L = list storing the labels of the k nearest neighbors to the ith test point + L = labels_train[np.argsort(dists[i])][0:k] + labels_predict[i] = np.argmax(np.bincount(L)) + return labels_predict + + + +def evaluate_knn(data_train,labels_train,data_test,labels_test,k): + # data_train the training data, + # labels_train the corresponding labels, + # data_test the testing data, + # labels_test the corresponding labels, and + # k the number of of neighbors. + num_val=labels_train.shape[0] + # dists = distance_matrix(labels_train,labels_test) + dists = distance_matrix(data_test,data_train) + labels_predict = knn.predict(dists,labels_train,k) + num_correct = np.sum(labels_predict == labels_train) + accuracy = (float(num_correct) / num_val)*100 + + return accuracy + + + +# For split=0.9, plot the variation of the accuracy as a function of k +# (from 1 to 20) + +path = "C:/Users/mylaa/Documents/ECL_2022/MOD/MOD_04_6_Apprentissage_profond_Intelligence_Artificielle/TD1/image-classification/data/cifar-10-batches-py" +data,labels = read_cifar.read_cifar(path) +split = 0.9 +data_train,labels_train,data_test,labels_test = read_cifar.split_dataset(data,labels,split) + +k = np.arange(1, 21, 1) +acc = evaluate_knn(data_train,labels_train,data_test,labels_test,k) +plt.plot(k, acc) +plt.title("variation of the accuracy following the value of k") +plt.xlabel("Values of k") +plt.ylabel("Values of the accuracy") +plt.show() + diff --git a/mlp.py b/mlp.py new file mode 100644 index 0000000..226844d --- /dev/null +++ b/mlp.py @@ -0,0 +1,254 @@ +import numpy as np +import read_cifar + +N = 30 # number of input data +d_in = 3 # input dimension +d_h = 3 # number of neurons in the hidden layer +d_out = 2 # output dimension (number of neurons of the output layer) + +# Random initialization of the network weights and biaises +w1 = 2 * np.random.rand(d_in, d_h) - 1 # first layer weights +b1 = np.zeros((1, d_h)) # first layer biaises +w2 = 2 * np.random.rand(d_h, d_out) - 1 # second layer weights +b2 = np.zeros((1, d_out)) # second layer biaises + +data = np.random.rand(N, d_in) # create a random data +targets = np.random.rand(N, d_out) # create a random targets + +data_train = np.random.rand(N,d_in) +labels_train = np.random.randint(1,d_out,N) + +data_test = np.random.rand(N,d_in) +labels_test = np.random.randint(1,d_out,N) + + + +split_factor=0.9 +#d_h=64 +learning_rate=0.1 +num_epoch=100 + +path = "C:/Users/mylaa/Documents/ECL_2022/MOD/MOD_04_6_Apprentissage_profond_Intelligence_Artificielle/TD1/image-classification/data/cifar-10-batches-py" +#data,labels = read_cifar.read_cifar(path) +#data_train,labels_train,data_test,labels_test = read_cifar.split_dataset(data,labels,split_factor) + + + +def sigmoid(x): + return 1 / (1 + np.exp(-x)) + +def sigmoid_derived(x): + return sigmoid(x)*(1-sigmoid(x)) + + + +def learn_once_mse(w1,b1,w2,b2,data,targets,learning_rate): +# performs one gradient descent step + + # Forward pass + a0 = data # the data are the input of the first layer + z1 = np.matmul(a0, w1) + b1 # input of the hidden layer + a1 = sigmoid(z1) # output of the hidden layer (sigmoid activation function) + z2 = np.matmul(a1, w2) + b2 # input of the output layer + a2 = sigmoid(z2) # output of the output layer (sigmoid activation function) + predictions = a2 # the predicted values are the outputs of the output layer + + # calculation of dw1, db1, dw2, db2 + dz2 = a2 - targets + dw2 = 1 / N *(np.matmul(a1.T,dz2)) + db2 = 1 / N *(np.sum(dz2,axis = 1,keepdims = True)) + dz1 = np.matmul(dz2,w2.T) * sigmoid_derived(z1) + dw1 = 1 / N *(np.matmul(a0.T,dz1)) + db1 = 1 / N *(np.sum(dz1,axis = 1,keepdims = True)) + + # gradient descent + w1 = w1 - learning_rate * dw1 + b1 = b1 - learning_rate * db1 + w2 = w2 - learning_rate * dw2 + b2 = b2 - learning_rate * db2 + + # Compute loss (MSE) + z1 = np.matmul(a0, w1) + b1 # input of the hidden layer + a1 = sigmoid(z1) # output of the hidden layer (sigmoid activation function) + z2 = np.matmul(a1, w2) + b2 # input of the output layer + a2 = sigmoid(z2) # output of the output layer (sigmoid activation function) + predictions = a2 # the predicted values are the outputs of the output laye + + loss = np.mean(np.square(predictions - targets)) + + return w1,b1,w2,b2,loss + + + + +def one_hot(M : np.ndarray): +# takes a (n)-D array as parameters and returns the corresponding (n+1)-D one-hot matrix + M_one = np.zeros((M.size, M.max()+1)) + M_one[np.arange(M.size),M] = 1 + return M_one + + + + +def learn_once_cross_entropy_0(w1,b1,w2,b2,data,targets,learning_rate): + + # Forward pass + a0 = data # the data are the input of the first layer + z1 = np.matmul(a0, w1) + b1 # input of the hidden layer + a1 = sigmoid(z1) # output of the hidden layer (sigmoid activation function) + z2 = np.matmul(a1, w2) + b2 # input of the output layer + a2 = sigmoid(z2) # output of the output layer (sigmoid activation function) + predictions = a2 # the predicted values are the outputs of the output layer + + # calculation of dw1, db1, dw2, db2 + dz2 = a2 - targets + dw2 = 1 / N *(np.matmul(a1.T,dz2)) + db2 = 1 / N *(np.sum(dz2,axis = 1,keepdims = True)) + dz1 = np.matmul(dz2,w2.T) * sigmoid_derived(z1) + dw1 = 1 / N *(np.matmul(a0.T,dz1)) + db1 = 1 / N *(np.sum(dz1,axis = 1,keepdims = True)) + + # gradient descent + w1 = w1 - learning_rate * dw1 + b1 = b1 - learning_rate * db1 + w2 = w2 - learning_rate * dw2 + b2 = b2 - learning_rate * db2 + + # Compute loss (cross entropy loss) + z1 = np.matmul(a0, w1) + b1 # input of the hidden layer + a1 = sigmoid(z1) # output of the hidden layer (sigmoid activation function) + z2 = np.matmul(a1, w2) + b2 # input of the output layer + a2 = sigmoid(z2) # output of the output layer (sigmoid activation function) + predictions = np.exp(a2)/np.sum(np.exp(a2)) # the predicted values are the outputs of the output layer + # must be a softmax + + loss = -np.mean(np.log(predictions)) + + return w1,b1,w2,b2,loss + + + + +def learn_once_cross_entropy(w1,b1,w2,b2,data,labels_train,learning_rate): + # labels_train a vector of size batch_size + # performs one gradient descent step using a cross entropy loss + + labels_train_one = one_hot(labels_train) + + # Forward pass + a0 = data # the data are the input of the first layer + z1 = np.matmul(a0, w1) + b1 # input of the hidden layer + a1 = sigmoid(z1) # output of the hidden layer (sigmoid activation function) + z2 = np.matmul(a1, w2) + b2 # input of the output layer + a2 = sigmoid(z2) # output of the output layer (sigmoid activation function) + predictions = a2 # the predicted values are the outputs of the output layer + + # calculation of dw1, db1, dw2, db2 + dz2 = a2 - labels_train_one + dw2 = 1 / N *(np.matmul(a1.T,dz2)) + db2 = 1 / N *(np.sum(dz2,axis = 1,keepdims = True)) + dz1 = np.matmul(dz2,w2.T) * sigmoid_derived(z1) + dw1 = 1 / N *(np.matmul(a0.T,dz1)) + db1 = 1 / N *(np.sum(dz1,axis = 1,keepdims = True)) + + # gradient descent + w1 = w1 - learning_rate * dw1 + b1 = b1 - learning_rate * db1 + w2 = w2 - learning_rate * dw2 + b2 = b2 - learning_rate * db2 + + # Compute loss (cross entropy loss) + z1 = np.matmul(a0, w1) + b1 # input of the hidden layer + a1 = sigmoid(z1) # output of the hidden layer (sigmoid activation function) + z2 = np.matmul(a1, w2) + b2 # input of the output layer + a2 = sigmoid(z2) # output of the output layer (sigmoid activation function) + predictions = np.exp(a2)/np.sum(np.exp(a2)) # the predicted values are the outputs of the output layer + # must be a softmax + + loss = -np.mean(np.log(predictions)) + + return w1,b1,w2,b2,loss + + + + +def train_mlp(w1,b1,w2,b2,data_train,labels_train,learning_rate,num_epoch): + # performs num_epoch of training steps + # num_epoch the number of training epoch + + labels_train_one = one_hot(labels_train) + + i=0 + train_accuracies = [] + # Forward pass + a0 = data_train # the data are the input of the first layer + z1 = np.matmul(a0, w1) + b1 # input of the hidden layer + a1 = sigmoid(z1) # output of the hidden layer (sigmoid activation function) + z2 = np.matmul(a1, w2) + b2 # input of the output layer + a2 = sigmoid(z2) # output of the output layer (sigmoid activation function) + predictions = a2 # the predicted values are the outputs of the output layer + + while i<num_epoch: + + # calculation of dw1, db1, dw2, db2 + dz2 = a2 - labels_train_one + dw2 = 1 / N *(np.matmul(a1.T,dz2)) + db2 = 1 / N *(np.sum(dz2,axis = 1,keepdims = True)) + dz1 = np.matmul(dz2,w2.T) * sigmoid_derived(z1) + dw1 = 1 / N *(np.matmul(a0.T,dz1)) + db1 = 1 / N *(np.sum(dz1,axis = 1,keepdims = True)) + + # gradient descent + w1 = w1 - learning_rate * dw1 + b1 = b1 - learning_rate * db1 + w2 = w2 - learning_rate * dw2 + b2 = b2 - learning_rate * db2 + + # Compute loss (cross entropy loss) + z1 = np.matmul(a0, w1) + b1 # input of the hidden layer + a1 = sigmoid(z1) # output of the hidden layer (sigmoid activation function) + z2 = np.matmul(a1, w2) + b2 # input of the output layer + a2 = sigmoid(z2) # output of the output layer (sigmoid activation function) + predictions = np.exp(a2)/np.sum(np.exp(a2)) # the predicted values are the outputs of the output layer + # must be a softmax + + loss = -np.mean(np.log(predictions)) + train_accuracies.append(loss) + + i=i+1 + + return w1,b1,w2,b2,train_accuracies + + + + +def test_mlp(w1,b1,w2,b2,data_test,labels_test): + # w1, b1, w2 and b2 the weights and biases of the network, + # data_test a matrix of shape (batch_size x d_in), and + # labels_test a vector of size batch_size, + # tests the network on the test set and returns test_accuracy the testing accuracy + + + return test_accuracy + + + + +def run_mlp_training(data_train,labels_train,data_test,labels_test,d_h,learning_rate,num_epoch): + # trains an MLP classifier and + # returns the training accuracies across epochs as a list of floats and the + # final testing accuracy as a float + + + + return train_accuracies,test_accuracy + + + + + + + + + + diff --git a/read_cifar.py b/read_cifar.py new file mode 100644 index 0000000..b3694a2 --- /dev/null +++ b/read_cifar.py @@ -0,0 +1,49 @@ +import pickle +from typing import Tuple +import os +import numpy as np + + + +def read_cifar_batch(path: str) -> Tuple[np.ndarray, np.ndarray]: + with open(path,"rb") as file: + dict=pickle.load(file,encoding="bytes") + data=np.array(dict[b"data"],dtype=np.float32) + labels=np.array(dict[b"labels"],dtype=np.int64) + + return data, labels + + + +def read_cifar(path): + data = np.array([],dtype=np.float32) + labels = np.array([],dtype=np.int64) + for b in range(1,6): + files = os.path.join(path, 'data_batch_%d' % (b, )) + X, Y = read_cifar_batch(files) + if np.size(data)==0: + data, labels = X,Y + else: + data = np.concatenate((data,X)) + labels = np.concatenate((labels,Y)) + data_test, labels_test = read_cifar_batch(os.path.join(path,'test_batch')) + data = np.concatenate((data,data_test)) + labels = np.concatenate((labels,labels_test)) + + return data, labels + + + +def split_dataset(data,labels,split): + k = np.random.permutation(np.size(data)) + data,labels=data[k],labels[k] + + data_nb=split*np.size(data) + + data_train=data[:int(data_nb)] + labels_train=labels[:int(data_nb)] + data_test=data[int(data_nb):] + labels_test=labels[int(data_nb):] + + return data_train,labels_train,data_test,labels_test + -- GitLab