Advertisement
mirosh111000

Курсова_робта_Мірошниченко(CNN)

Nov 30th, 2024 (edited)
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.22 KB | None | 0 0
  1. import numpy as np
  2. from tensorflow.keras.datasets import mnist
  3. from tensorflow.keras.utils import to_categorical
  4. import os
  5. import datetime as dt
  6. import matplotlib.pyplot as plt
  7. from sklearn.metrics import accuracy_score, classification_report, log_loss
  8. import pandas as pd
  9. import re
  10. from matplotlib.colors import Normalize
  11. import seaborn as sns
  12.  
  13.  
  14. class CNN:
  15.     def __init__(self, input_shape=(28, 28, 1), num_classes=10, num_neurons=128, learning_rate=0.01, filter_size=5, num_filter1=8, num_filter2=7, pool_size=2, stride=2):
  16.         self.input_shape = input_shape
  17.         self.num_classes = num_classes
  18.         self.num_neurons = num_neurons
  19.         self.learning_rate = learning_rate
  20.         self.filter_size = filter_size
  21.         self.num_filter1 = num_filter1
  22.         self.num_filter2 = num_filter2
  23.         self.pool_size = pool_size
  24.         self.stride = stride
  25.         self.loss = []
  26.         self.accuracy = []
  27.         self.initialize_weights()
  28.  
  29.     def initialize_weights(self):
  30.        
  31.         self.W1 = np.random.normal(0, 0.05, size=(self.num_filter1, self.filter_size, self.filter_size, self.input_shape[2]))
  32.         self.b1 = np.zeros(self.num_filter1)
  33.        
  34.         self.W2 = np.random.normal(0, 0.05, size=(self.num_filter2, self.filter_size, self.filter_size, self.num_filter1))
  35.         self.b2 = np.zeros(self.num_filter2)
  36.        
  37.         pool1_h = (self.input_shape[0] - self.filter_size + 1)  
  38.         pool1_w = (self.input_shape[0] - self.filter_size + 1)
  39.        
  40.         pool2_h = (pool1_h - self.filter_size + 1)
  41.         pool2_w = (pool1_w - self.filter_size + 1)
  42.        
  43.         final_h = pool2_h // 2  
  44.         final_w = pool2_w // 2  
  45.    
  46.         flattened_size = self.num_filter2 * final_h * final_w
  47.        
  48.         self.W3 = np.random.normal(0, 0.05, size=(flattened_size, self.num_neurons))
  49.         self.b3 = np.zeros(self.num_neurons)
  50.        
  51.         self.W4 = np.random.normal(0, 0.05, size=(self.num_neurons, self.num_classes))
  52.         self.b4 = np.zeros(self.num_classes)
  53.  
  54.     def relu(self, x):
  55.         return np.maximum(0, x)
  56.  
  57.     def relu_derivative(self, x):
  58.         return (x > 0).astype(float)
  59.  
  60.     def softmax(self, x):
  61.         return np.exp(x) / np.sum(np.exp(x))
  62.  
  63.     def convolve(self, X, W, b, stride=1):
  64.         n_filters, kernel_h, kernel_w, depth = W.shape
  65.         h, w, d = X.shape
  66.  
  67.         output_h = (h - kernel_h) // stride + 1
  68.         output_w = (w - kernel_w) // stride + 1
  69.         output = np.zeros((output_h, output_w, n_filters))
  70.  
  71.         for f in range(n_filters):
  72.             for i in range(0, output_h * stride, stride):
  73.                 for j in range(0, output_w * stride, stride):
  74.                     region = X[i:i+kernel_h, j:j+kernel_w, :]
  75.                     output[i // stride, j // stride, f] = np.sum(region * W[f]) + b[f]
  76.         return output
  77.  
  78.     def convolve_backward(self, d_out, X, W, stride=1):
  79.  
  80.         n_filters, kernel_h, kernel_w, depth = W.shape
  81.         h, w, d = X.shape
  82.  
  83.         d_X = np.zeros_like(X)
  84.         d_W = np.zeros_like(W)
  85.         d_b = np.zeros(W.shape[0])
  86.  
  87.         output_h = (h - kernel_h) // stride + 1
  88.         output_w = (w - kernel_w) // stride + 1
  89.  
  90.         for f in range(n_filters):
  91.             for i in range(output_h):
  92.                 for j in range(output_w):
  93.                     region = X[i*stride:i*stride+kernel_h, j*stride:j*stride+kernel_w, :]
  94.                     d_W[f] += region * d_out[i, j, f]
  95.                     d_X[i*stride:i*stride+kernel_h, j*stride:j*stride+kernel_w, :] += W[f] * d_out[i, j, f]
  96.             d_b[f] = np.sum(d_out[:, :, f])
  97.         return d_X, d_W, d_b
  98.  
  99.     def max_pool(self, X):
  100.         h, w, n_filters = X.shape
  101.         pool_size = self.pool_size
  102.         stride = self.stride
  103.         output_h = (h - pool_size) // stride + 1
  104.         output_w = (w - pool_size) // stride + 1
  105.         output = np.zeros((output_h, output_w, n_filters))
  106.  
  107.         self.pool_mask = np.zeros_like(X)
  108.  
  109.         for f in range(n_filters):
  110.             for i in range(0, output_h * stride, stride):
  111.                 for j in range(0, output_w * stride, stride):
  112.                     region = X[i:i+pool_size, j:j+pool_size, f]
  113.                     max_val = np.max(region)
  114.                     output[i // stride, j // stride, f] = max_val
  115.                     self.pool_mask[i:i+pool_size, j:j+pool_size, f] = (region == max_val)
  116.         return output
  117.  
  118.     def max_pool_backward(self, d_out):
  119.         d_out_repeated = np.repeat(np.repeat(d_out, self.pool_size, axis=0), self.pool_size, axis=1)
  120.         d_X = self.pool_mask * d_out_repeated
  121.         return d_X
  122.  
  123.     def forward(self, X):
  124.  
  125.         self.X1 = self.convolve(X, self.W1, self.b1)
  126.         self.A1 = self.relu(self.X1)
  127.  
  128.         self.X2 = self.convolve(self.A1, self.W2, self.b2)
  129.         self.A2 = self.relu(self.X2)
  130.         self.P2 = self.max_pool(self.A2)
  131.  
  132.         self.flattened = self.P2.flatten()
  133.  
  134.         self.X3 = np.dot(self.flattened, self.W3) + self.b3
  135.         self.A3 = self.relu(self.X3)
  136.    
  137.         self.X4 = np.dot(self.A3, self.W4) + self.b4
  138.         self.Y_hat = self.softmax(self.X4)
  139.    
  140.         return self.Y_hat
  141.  
  142.     def backward(self, X, y):
  143.        
  144.         d_X4 = self.Y_hat - y  
  145.  
  146.         d_W4 = np.outer(self.A3, d_X4)
  147.         d_b4 = d_X4
  148.  
  149.         d_A3 = np.dot(d_X4, self.W4.T)
  150.        
  151.         d_X3 = self.relu_derivative(self.X3) * d_A3
  152.  
  153.         d_W3 = np.outer(self.flattened, d_X3)
  154.         d_b3 = d_X3
  155.  
  156.         d_flattened = np.dot(d_X3, self.W3.T)
  157.  
  158.         d_P2 = d_flattened.reshape(self.P2.shape)
  159.         d_P2 = self.max_pool_backward(d_P2)
  160.  
  161.         d_A2 = self.relu_derivative(self.X2) * d_P2
  162.    
  163.         d_W2 = np.zeros_like(self.W2)
  164.         d_b2 = np.zeros_like(self.b2)
  165.        
  166.         d_X2, d_W2, d_b2 = self.convolve_backward(d_A2, self.A1, self.W2)
  167.    
  168.         d_A1 = self.relu_derivative(self.X1) * d_X2
  169.    
  170.         d_W1 = np.zeros_like(self.W1)
  171.         d_b1 = np.zeros_like(self.b1)
  172.         d_X1, d_W1, d_b1 = self.convolve_backward(d_A1, X, self.W1)
  173.    
  174.         self.W4 -= self.learning_rate * d_W4
  175.         self.b4 -= self.learning_rate * d_b4
  176.         self.W3 -= self.learning_rate * d_W3
  177.         self.b3 -= self.learning_rate * d_b3
  178.         self.W2 -= self.learning_rate * d_W2
  179.         self.b2 -= self.learning_rate * d_b2
  180.         self.W1 -= self.learning_rate * d_W1
  181.         self.b1 -= self.learning_rate * d_b1
  182.  
  183.  
  184.  
  185.     def train(self, X_train, y_train, epochs=10, batch_size=32, early_stopping_rounds=np.inf):
  186.         num_samples = X_train.shape[0]
  187.         start_time = dt.datetime.now()
  188.         ready = 0
  189.         for epoch in range(epochs):
  190.             loss, num_correct = 0, 0
  191.             for i in range(0, num_samples, batch_size):
  192.                
  193.                 X_batch = X_train[i:i + batch_size]
  194.                 y_batch = y_train[i:i + batch_size]
  195.                 ready += len(X_batch)
  196.  
  197.                 for x, y in zip(X_batch, y_batch):
  198.                    
  199.                     self.forward(x)
  200.                     loss += log_loss(y_true=y, y_pred=self.Y_hat)
  201.                    
  202.                     if np.argmax(y) == np.argmax(self.Y_hat):
  203.                         num_correct += 1
  204.                        
  205.                     self.backward(x, y)
  206.  
  207.                 prcnt = (ready)/(num_samples*epochs) * 100
  208.                 print(f'№{ready}/{num_samples*epochs} - {round(prcnt, 2)}% | total time: {dt.datetime.now() - start_time} | time remaining: {(dt.datetime.now() - start_time) / prcnt * (100 - prcnt)} | end time: {dt.datetime.now() + (dt.datetime.now() - start_time) / prcnt * (100 - prcnt)}', end='\r')
  209.                 os.system('cls' if os.name == 'nt' else 'clear')
  210.                    
  211.             loss /= num_samples
  212.             num_correct /= num_samples
  213.             self.loss.append(loss)
  214.             self.accuracy.append(num_correct)
  215.  
  216.             if epoch + 1 > early_stopping_rounds:
  217.                 if np.argmin(self.loss) < epoch - early_stopping_rounds:
  218.                     print(f'\nЗупинка на епохі {epoch+1}')
  219.                     break
  220.  
  221.  
  222.     def predict(self, X):
  223.         return np.array([np.argmax(self.forward(x)) for x in X])
  224.  
  225.  
  226. def plot_values_counts(df):
  227.     plt.figure(figsize=(15, 4))
  228.     df['target'].value_counts().plot(kind='barh', color='skyblue')
  229.     for index, value in enumerate(df['target'].value_counts()):
  230.         plt.text(value, index, f'{value}', va='center')
  231.     plt.grid()
  232.     plt.title('Кількість кожного з класів в навчальній вибірці')
  233.     plt.ylabel('Клас')
  234.     plt.xlabel('Кількість')
  235.     plt.show()
  236.  
  237. def plot_classification_report(report):
  238.  
  239.     pattern = r'\s*(\d+)\s+(\d+\.\d{2})\s+(\d+\.\d{2})\s+(\d+\.\d{2})\s+(\d+)\n?'
  240.     matches = re.findall(pattern, report)
  241.     matches = pd.DataFrame(matches, columns=['Class', 'Precision', 'Recall', 'F1-score', 'Support'])
  242.    
  243.     for col in matches.columns: matches[col] = matches[col].astype(float)
  244.    
  245.     for col in ['Precision', 'Recall', 'F1-score']:
  246.         plt.figure(figsize=(10, 4))
  247.        
  248.         cmap = plt.get_cmap('coolwarm')
  249.         norm = Normalize(0, 1)
  250.    
  251.         for index, value in enumerate(matches[col]):
  252.             gradient = np.linspace(0, value, 100)
  253.             gradient = gradient.reshape(1, -1)
  254.            
  255.             plt.imshow(gradient, aspect='auto', cmap=cmap, norm=norm, extent=[0, value, index - 0.4, index + 0.4])
  256.             plt.text(value - 0.05, index, f'{value:.2f}', va='center')
  257.        
  258.         plt.grid(True, axis='x')
  259.         plt.title(f'{col} кожного з класів')
  260.         plt.ylabel('Клас')
  261.         plt.xlabel(col)
  262.         plt.yticks(ticks=np.arange(len(matches)), labels=matches['Class'].astype(int))
  263.         plt.xlim(0, 1)
  264.         plt.ylim(-0.5, len(matches) - 0.5)
  265.        
  266.         plt.show()
  267.  
  268.         return matches
  269.  
  270.  
  271. (X_train, y_train), (X_test, y_test) = mnist.load_data()
  272.  
  273. df = pd.DataFrame(y_train)
  274. df['target'] = y_train
  275.  
  276. plt.figure(figsize=(10,5))
  277. for i in range(5):
  278.     plt.subplot(1, 5, i + 1)
  279.     plt.imshow(X_train[i], cmap='gray_r')
  280.     plt.title(f"Label: {y_train[i]}")
  281.     plt.axis("off")
  282. plt.show()
  283.  
  284. plot_values_counts(df)
  285.  
  286. X_train = X_train.astype("float32") / 255.0
  287. X_test = X_test.astype("float32") / 255.0
  288.  
  289. X_train = X_train[..., np.newaxis]
  290. X_test = X_test[..., np.newaxis]
  291.  
  292. y_train_labels = np.copy(y_train)
  293. y_test_labesl = np.copy(y_test)
  294.  
  295. y_train = to_categorical(y_train, 10)
  296. y_test = to_categorical(y_test, 10)
  297.  
  298. model = CNN(learning_rate=0.01)
  299.  
  300. model.train(X_train, y_train, epochs=12, batch_size=256, early_stopping_rounds=2)
  301.  
  302. y_pred = model.predict(X_test)
  303.  
  304. text = classification_report(y_test_labesl, y_pred)
  305. matches = plot_classification_report(text)
  306. print(text)
  307. print(f'Точність на тестових даних: {accuracy_score(y_test_labesl, y_pred)*100}%')
  308.  
  309. corr_df = df.target.value_counts()
  310. corr_df = pd.DataFrame(corr_df.values, columns=['Support_train'], index=corr_df.index)
  311. corr_df = corr_df.sort_index()
  312. corr_df = pd.concat([corr_df, matches.iloc[:, 1:-1]], axis=1)
  313. corr_df.corr()
  314.  
  315. plt.figure(figsize=(5, 2))
  316. sns.heatmap(corr_df.corr()[['F1-score', 'Precision', 'Recall']].loc[['Support_train']], annot=True, cmap='coolwarm', vmin=-1, vmax=1)
  317. plt.show()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement