Небольшая нейронная сеть на 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/post/716844/


Интересные статьи

Интересные статьи

Статья направлена на решение проблемы "зависания" выгрузки результатов опросов при использовании модуля Vote 1С-Битрикс в случае, если в опросе много вопросов или ответов. Так-же в статье реализована ...
Как обуздать GPT-3 Компания OpenAI готовится к открытию коммерческого API к GPT-3, своей самой новой и крупной нейросети для генерации текста. В рамках подготовки компания создаёт систем...
Парусник “NaN” сигналит SOS (See Our Success) Raspberry Pi, азбука Морзе и MQTT: вместе веселее Меня зовут Вова Балакин, я из московской школы на Юго-Востоке имени Маршала В.И.Чуйков...
Flipper Zero — проект карманного мультитула для хакеров в формфакторе тамагочи, который я разрабатываю с друзьями. Предыдущий пост [1]. Много всего произошло с момента первого поста про фл...
Эта статья про модель на основе Байесовской сети, которая описывает котировки мировых валют. Я покажу на основе простой метрики, что паттерн поведения котировок мировых валют за последние два...