Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import numpy as np
- import matplotlib.pyplot as plt
- import os
- from PIL import Image
- from scipy.ndimage import center_of_mass
- from scipy.ndimage import shift
- import datetime as dt
- import os
- import pandas as pd
- from IPython.display import clear_output
- from sklearn.metrics import accuracy_score, classification_report
- import re
- from matplotlib.colors import Normalize
- from matplotlib.cm import ScalarMappable
- def plot_classification_report(report, type='', prob=''):
- pattern = r'\s*(\d+)\s+(\d+\.\d{2})\s+(\d+\.\d{2})\s+(\d+\.\d{2})\s+(\d+)\n?'
- matches = re.findall(pattern, report)
- matches = pd.DataFrame(matches, columns=['Class', 'Precision', 'Recall', 'F1-score', 'Support'])
- for col in matches.columns: matches[col] = matches[col].astype(float)
- for col in ['Precision', 'Recall', 'F1-score']:
- plt.figure(figsize=(10, 4))
- cmap = plt.get_cmap('coolwarm')
- norm = Normalize(0, 1)
- for index, value in enumerate(matches[col]):
- gradient = np.linspace(0, value, 100)
- gradient = gradient.reshape(1, -1)
- plt.imshow(gradient, aspect='auto', cmap=cmap, norm=norm, extent=[0, value, index - 0.4, index + 0.4])
- if value > 0:
- plt.text(value - 0.05, index, f'{value:.2f}', va='center')
- plt.grid(True, axis='x')
- plt.title(f'{col} кожного з класів (Рівень {type} {prob}%)')
- plt.ylabel('Клас')
- plt.xlabel(col)
- plt.yticks(ticks=np.arange(len(matches)), labels=matches['Class'].astype(int))
- plt.xlim(0, 1)
- plt.ylim(-0.5, len(matches) - 0.5)
- plt.show()
- def visualize_symbols(symbols):
- fig, axes = plt.subplots(1, len(symbols), figsize=(7, 5))
- for ax, (symbol, pattern) in zip(axes, symbols.items()):
- ax.imshow(pattern.reshape(height, width), cmap="gray")
- ax.set_title(symbol)
- ax.axis("off")
- plt.show()
- def center_image_before_resize(img):
- cy, cx = center_of_mass(img)
- shift_y = img.shape[0] // 2 - cy
- shift_x = img.shape[1] // 2 - cx
- centered_img = shift(img, shift=[shift_y, shift_x], mode='constant', cval=0)
- return centered_img
- def blackout_noise(image, blackout_prob=0.2):
- noisy_image = np.copy(image)
- black_pixels = np.where(image == 0)
- num_black_pixels = len(black_pixels[0])
- for i in range(num_black_pixels):
- random_num = np.random.random()
- if random_num <= blackout_prob:
- noisy_image[black_pixels[0][i]] = 1
- return noisy_image
- def add_random_noise(image, noise_prob=0.1):
- black_pixels = np.where(image == 0)
- num_black_pixels = len(black_pixels[0])
- noisy_image = blackout_noise(image, blackout_prob=noise_prob)
- for i in range(num_black_pixels):
- random_num = np.random.random()
- if random_num <= noise_prob:
- random_idx = np.random.randint(0, len(noisy_image))
- noisy_image[random_idx] = 0
- return noisy_image
- def generate_noisy_symbols(method='blackout', blackout_prob=0.2, noise_prob=0.2):
- noisy_symbols = {}
- for i in range(N):
- if method == 'blackout':
- noisy_symbols[str(i)] = blackout_noise(symbols[str(i)], blackout_prob)
- elif method == 'add_random':
- noisy_symbols[str(i)] = add_random_noise(symbols[str(i)], noise_prob)
- return noisy_symbols
- def one_hot_encode(label, num_classes=10):
- y = np.zeros(num_classes)
- y[label] = 1
- return y
- def activation_function(s, T):
- activations = []
- for i in s:
- if i <= 0: activations.append(0)
- elif i >= T: activations.append(T)
- else: activations.append(i)
- return np.array(activations)
- class HammingLayer:
- def __init__(self, reference_images):
- self.M = len(reference_images[0])
- self.weights = np.copy(reference_images).T / 2
- self.bias = np.array([self.M / 2 for _ in range(len(reference_images))])
- def activate(self, x):
- activation = np.dot(x, self.weights) + self.bias
- return activation_function(s=activation, T=self.M)
- class MaxNetLayer:
- def __init__(self, num_neurons, epsilon):
- self.num_neurons = num_neurons
- self.epsilon = epsilon
- self.weights = np.full((num_neurons, num_neurons), -epsilon)
- np.fill_diagonal(self.weights, 1)
- def activate(self, x, T):
- y = x.copy()
- _ = 0
- while np.sum(y > 0) > 1:
- y = activation_function(s=np.dot(y, self.weights), T=T)
- _ += 1
- if _ > 100000:
- # print('break')
- break
- return y
- class HammingNetwork:
- def __init__(self, reference_images, epsilon=0.1):
- self.hamming_layer = HammingLayer(reference_images)
- self.maxnet_layer = MaxNetLayer(len(reference_images), epsilon)
- def predict(self, x):
- hamming_activations = self.hamming_layer.activate(x)
- # print(f'hamming_activations = {hamming_activations}')
- maxnet_output = self.maxnet_layer.activate(hamming_activations, T=self.hamming_layer.M)
- # print(f'maxnet_output = {maxnet_output}')
- return np.argmax(maxnet_output)
- width = 28
- height = 28
- N = 10
- num = 10
- M = width * height
- digit_images = []
- for i in range(N):
- img = np.array(Image.open(f'D:/SUMDU/4 курс/Моделювання нейронних мереж/pr9/{i}.png').convert('L'))
- centered_img = center_image_before_resize(img)
- centered_img = np.array(centered_img)[num:-num, num:-num]
- centered_img = np.array(Image.fromarray(centered_img).resize((width, height)))
- centered_img = np.where(centered_img > 255/2, 1, 0)
- digit_images.append(centered_img.reshape(M))
- # plt.imshow(centered_img, cmap='gray')
- # plt.show()
- symbols = {str(i): digit for i, digit in enumerate(digit_images)}
- visualize_symbols(symbols)
- noisy_symbols_blackout = generate_noisy_symbols(method='blackout', blackout_prob=0.2)
- noisy_symbols_random = generate_noisy_symbols(method='add_random', noise_prob=0.2)
- visualize_symbols(noisy_symbols_blackout)
- visualize_symbols(noisy_symbols_random)
- reference_images = np.copy([i for _, i in symbols.items()])
- eps = 1 / N * 0.1
- model = HammingNetwork(reference_images, epsilon=eps)
- n = 10000
- df = pd.DataFrame(columns=['blackout_input', 'blackout_prob', 'noise_input', 'noise_prob', 'target', 'blackout_pred', 'blackout_error, %', 'noise_pred', 'noise_error, %'], index=[i for i in range(n)])
- symbol = 0
- df_res = pd.DataFrame(columns=['blackout_error, %', 'noise_error, %', 'blackout_report', 'noise_report'])
- df_res.index.name = 'prob, %'
- num_prob = 100
- start_time = dt.datetime.now()
- for _, prob in enumerate(np.linspace(0, 1, num_prob)):
- for i in range(n):
- df['target'].iloc[i] = symbol
- df['blackout_prob'].iloc[i] = prob
- df['noise_prob'].iloc[i] = prob
- df['blackout_input'].iloc[i] = blackout_noise(symbols[str(symbol)], blackout_prob=prob)
- df['noise_input'].iloc[i] = add_random_noise(symbols[str(symbol)], noise_prob=prob)
- df['blackout_pred'].iloc[i] = model.predict(df['blackout_input'].iloc[i])
- df['noise_pred'].iloc[i] = model.predict(df['noise_input'].iloc[i])
- if symbol == 9:
- symbol = 0
- else:
- symbol += 1
- df['target'] = df['target'].astype(int)
- df['blackout_pred'] = df['blackout_pred'].astype(int)
- df['noise_pred'] = df['noise_pred'].astype(int)
- df_res.loc[prob*100] = [(1 - accuracy_score(y_true=df['target'], y_pred=df['blackout_pred'])) * 100,
- (1 - accuracy_score(y_true=df['target'], y_pred=df['noise_pred'])) * 100,
- classification_report(y_true=df['target'], y_pred=df['blackout_pred']),
- classification_report(y_true=df['target'], y_pred=df['noise_pred']),
- ]
- prcnt = (_+1)/num_prob * 100
- print(f'№{_+1}/{num_prob} - {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')
- os.system('cls' if os.name == 'nt' else 'clear')
- plt.figure(figsize=(10, 4))
- plt.plot(df_res.index, df_res.iloc[:, 0], c='blue', label='Затирання')
- plt.plot(df_res.index, df_res.iloc[:, 1], c='red', label='Шум')
- plt.legend()
- plt.title('Відсоток неправильно класифікованих цифр')
- plt.xlabel('Noise level [%]')
- plt.ylabel('Percentage of error, [%]')
- plt.grid()
- plt.show()
- for i in range(len(df_res)):
- plot_classification_report(df_res.blackout_report.iloc[i], type='Затирання', prob=round(df_res.index[i], 2))
- plot_classification_report(df_res.noise_report.iloc[i], type='Шум', prob=round(df_res.index[i], 2))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement