Небольшая нейронная сеть на Raspberry Pi Pico

—

от автора

Всем читателям привет! P.S Это мой первый пост, поэтому сильно не судите

В этом посте я вам покажу как создать достаточно эффективную нейронную сеть на Raspberry Pi Pico!

Для начала каким-либо образом копируем этот код в память pico:

from random import random from math import exp  class NeyroNet: def __init__(self, n_inputs, hiddens_layer, n_outputs): self.network = list()  self.n_outputs = n_outputs  hidden_layer = [{'weights':[random() for i in range(n_inputs + 1)]} for i in range(hiddens_layer[0])] self.network.append(hidden_layer)  for layer in hiddens_layer[1:]: hidden_layer = [{'weights':[random() for i in range(len(self.network[-1])+1)]} for i in range(layer)] self.network.append(hidden_layer)  output_layer = [{'weights':[random() for i in range(hiddens_layer[-1] + 1)]} for i in range(n_outputs)] self.network.append(output_layer)  def activate(self, weights, inputs): activation = weights[-1] for i in range(len(weights)-1): activation += weights[i] * inputs[i] return activation  def transfer(self, activation): return 1.0 / (1.0 + exp(-activation))  def forward_propagate(self, row): inputs = row for layer in self.network: new_inputs = [] for neuron in layer: activation = self.activate(neuron['weights'], inputs) neuron['output'] = self.transfer(activation) new_inputs.append(neuron['output']) inputs = new_inputs return inputs  def transfer_derivative(self, output): return output * (1.0 - output)  def backward_propagate_error(self, expected): for i in reversed(range(len(self.network))): layer = self.network[i] errors = list() if i != len(self.network)-1: for j in range(len(layer)): error = 0.0 for neuron in self.network[i + 1]: error += (neuron['weights'][j] * neuron['delta']) errors.append(error) else: for j in range(len(layer)): neuron = layer[j] errors.append(expected[j] - neuron['output']) for j in range(len(layer)): neuron = layer[j] neuron['delta'] = errors[j] * self.transfer_derivative(neuron['output'])  def update_weights(self, row, l_rate): for i in range(len(self.network)): inputs = row[:-1] if i != 0: inputs = [neuron['output'] for neuron in self.network[i - 1]] for neuron in self.network[i]: for j in range(len(inputs)): neuron['weights'][j] += l_rate * neuron['delta'] * inputs[j] neuron['weights'][-1] += l_rate * neuron['delta']  def train_network(self, train, l_rate, n_epoch, err_val_threshold=0): for epoch in range(n_epoch): sum_error = 0 for row in train: outputs = self.forward_propagate(row) expected = [0 for i in range(self.n_outputs)] expected[row[-1]] = 1 sum_error += sum([(expected[i]-outputs[i])**2 for i in range(len(expected))]) self.backward_propagate_error(expected) self.update_weights(row, l_rate) pdat = '>epoch=%d, lrate=%.1f, error=%.10f' % (epoch, l_rate, sum_error) print(pdat, end='\r') if(sum_error < err_val_threshold): print(' ' * len(pdat), end='\r') print('THRESHOLD WITH EPOCH > ' + str(epoch)) break  def predict(self, row): outputs = self.forward_propagate(row) return outputs.index(max(outputs))  def save(self, filename): with open(filename, 'w') as sv: sv.write(str(self.network)) sv.close()  def load(self, filename): with open(filename, 'r') as sv: data = sv.read() sv.close() self.network = eval(data)  

Называем файл как угодно

Далее заходим в консоль pico через minicom или через thonny

Прописываем для инициализации нейронной сети

import <скопированный файл без приставки .py> net = NeyroNet(3, [6], 2) # 3 - Сколько входов, [6] - Это список слоёв (в первом слое 6 нейронов), 2 - сколько выходов

Далее берём любой dataset

dataset = [[1, 0 ,0 ,1], [1, 1, 0, 1], [0, 1, 1, 0], [0, 0, 1, 0]]

Вы спросите: «Почему у тебя в каждом элементе по 4 значения а входов всего 4?»

Дело в том что самое последнее значение в элементе это и есть выходные данные, а все остальные — это входные!

После этого обучаем нейросеть

net.train_network(dataset, l_rate=0.5, n_epoch=10000, err_val_threshold=0.0009)

P.S. параметр err_val_threshold нужен для того чтобы не ждать пока нейросеть пройдёт все эпохи, этот параметр указывает пороговое значение ошибки т.e. если ошибка будет меньше этого значения обучение прекратится!

Ну вот мы и обучили нейросеть! Теперь давайте проверим что она выдаёт!

Как мы помним у нас всего выходных класса

net.predict([1, 0, 1]) # возвращает 1 т.е какой выход (начинается с 0) net.forward_propagate([0, 0, 0]) # возвращает [0.99998464, 0.00006544]

И чтобы сохранить текущие веса нужно прописать:

net.save('<имя файла>')

А чтобы загрузить веса сети нужно воопервых при создании объекта сети нужно указать столько же выходов, сколько и было сохранено, а иначе будет ошибка!

net.load('<имя файла>')

Вот и всё!

Надеюсь вам понравилась статья!


ссылка на оригинал статьи https://habr.com/ru/articles/716844/