Tags: нейронная сеть распознавать поворот головы
Введение
Постановка задачи
Оценка возможностей распознавать поворот лица через машинное обучение
Программный код (вариант 1)
Программный код (вариант 2)
Адекватность и оптимальность нейронной сети для распознавания поворота головы
Полезные ссылки
Введение
Как не зная алгоритм, а просто имея данные и ответ, получить из них алгоритм? Альтернатива традиционному алгоритмическому подходу – нейронная сеть, которую можно обучать предсказывать результат по выборке для обучения.
На рисунке демонстрируются 2 подхода к решению задачи пересчета температуры из Цельсия в Фаренгейт.
При создании среды для обучения мы всегда должны помнить, что наличие хорошего показателя с набором данных для обучения не обязательно означает, что модель хорошо адаптируется к новым данным. Конечная цель любой модели машинного обучения — делать надежные прогнозы для новых, неизвестных данных.
Весь смысл машинного обучения состоит в том, чтобы предсказать вещи, основанные на образцах и других факторах, с которыми он обучался.
Машинное обучение проще, чем традиционное программирование. В процессе программирования вам необходимо учитывать каждый случай в исходных данных, адаптировать под него логику программы и правила. В то же самое время, используя машинное обучение вы, по сути, тренируете компьютер самому находить правила на основе примеров.
Постановка задачи
На рисунке ниже отображен результат запуска программы, описанной в статье Обнаружение лица и выделение характерных точек.
При повороте головы изменяются размеры сторон треугольника, вершины которого соединяют ключевые точки лица. Эти данные можно использовать для распознавания поворота головы — вправо (Right) и влево (Left).
При алгоритмическом подходе к решению такой задачи достаточно выполнять проверку, какая из сторон больше. Если стороны равны, то положение промежуточное (Center).
Попробуем решить эту задачу через обучение нейронной сети (персептрона).
На вход сети подается пара сигналов (признаков лица), которые представляют нормализованные расстояния от точек глаз до точки носа. Под нормализацией здесь понимается то, что признаки-расстояния отнесены к расстоянию между глазами. Нормализация обеспечивает независимость признаков от удаленности камеры.
Каждая пара сигналов (X) берется с кадров (frames) от веб-камеры. При обучении НС сигнал на выходе (y) принимается:
- 1 — при положении головы Right;
- 0 — при положении головы Left.
При тестировании уже обученной сети сигнал на выходе должен быть между 1 и 0:
- y> 0.9 — если положение головы Right;
- y< 0.1 — если положение головы Left;
- 0.1 < y <0.9 — если положение головы Center
Оценка возможностей распознавать поворот лица через машинное обучение
Для оценки возможности распознавать поворот лица через машинное обучение выполним следующее:
- Получим входные данные (пара нормализованных расстояний от точки носа до точек глаз) для нескольких кадров (Frames) с поворотом головы вправо и влево, используя программу из статьи Обнаружение лица и выделение характерных точек в реальном времени
- Обучим и протестируем нейронную сеть на основе этих данных, используя программу из статьи Простейшие нейронные сети на Python в Visual Studio.
Входные данные для обучения:
- для поворота головы направо
В левом углу отображаются текущие данные (размеры сторон треугольника), которые могут подаваться на вход нейронной сети. Эти же данные для каждого фрейма отображаются в окне консоли Из них выбираем для обучения НС наиболее разнообразные.
- для поворота головы налево
Входные данные для тестирования:
- для поворота головы направо
- для поворота головы налево
Ниже представлены отобранные данные для обучения и тестирования НС
В первой строке указаны входные данные, ниже — ожидаемые выходные сигналы.
Программный код для обучения и тестирования приводится ниже.
import numpy as np # обучающая выборка входных и выходных данных X = np.array([[0.838,0.661],[1.095,0.679],[0.958,0.701], [0.604,1.060],[0.695,1.082],[0.532,1.115]]) y = np.array([[0,0,0,1,1,1]]).T # T-транспонирование матрицы # инициализация случайных весов (от -1 до +1) синапсов np.random.seed(1) synapses_hidden = 2 * np.random.random((2,3)) - 1 # 2*3 - hidden слой synapses_output = 2 * np.random.random((3,1)) - 1 # 3*1 - output слой # обучение сети - цикл из 10000 повторений for j in range(10000): # Входной слой ( 2 входа ) l0 = X # Скрытый слой ( 3 скрытых нейрона ) l1 = 1 / (1 + np.exp(-(l0.dot(synapses_hidden)))) # Выходной слой ( 1 выходной нейрон ) l2 = 1 / (1 + np.exp(-(l1.dot(synapses_output)))) # вычисляем ошибку (используем дельта-правило) l2_delta = (y - l2) * (l2 * (1 - l2)) # получаем ошибку на скрытом слое (используем дельта-правило) l1_delta = l2_delta.dot(synapses_output.T) * (l1 * (1 - l1)) # корректируем веса от скрытых нейронов к выходу synapses_output += l1.T.dot(l2_delta) # корректируем веса от входов к скрытым нейронам synapses_hidden += l0.T.dot(l1_delta) # Печать сигналов на выходе после последнего цикла обучения print('Результаты обучения') print(l2) # Тестирование с новыми данными на входе X = np.array([[0.982,0.680],[1.030,0.700],[0.885,0.690], [0.685,1.064],[0.751,0.937],[0.797,0.833]]) # Входной слой ( 2 входа ) l0 = X # Скрытый слой ( 3 скрытых нейрона ) l1 = 1 / (1 + np.exp(-(l0.dot(synapses_hidden)))) # Выходной слой ( 1 выходной нейрон ) l2 = 1 / (1 + np.exp(-(l1.dot(synapses_output)))) print('Результаты тестирования') print(l2)
Результаты запусков программы с различным количеством циклов обучения (10000 и 100000):
Длительность обучения 1 сек и 5 сек.
Выделенные красным цветом числа не соответствует ожидаемому результату (далеки от единицы). Однако, это можно объяснить тем, что этот результат получен для входных сигналов [0.797,0.833] , которые определяют положение головы, близкое к центральному (Center).
Для обучения использовалось данные всего лишь с трех кадров. Хотя результаты тестирования достаточно хорошие, однако нет гарантии, что модель будет адаптироваться ко всему многообразию данных в пределах поставленной задачи, поскольку для тестирования использовалось мало кадров.
Вводить данные вручную и тестировать лишь по цифрам — неэффективно. Возникает необходимость разработать программу, в которой реализуется автоматическое считывание данных с фреймов от веб-камеры. Интерфейс такой программы описывается ниже.
Программный код (вариант 1)
При запуске программы появляется диалоговое окно. При нажатии на кнопку Start запускается процесс обучения — если включена опция Training, или процесс распознавания — если включена опция Recognition. Перед началом обучения (еще до включения веб-камеры) появляется msgbox с вопросом: «Right side?». При положительном ответе на выход нейронной сети будет подаваться значение сигнала 1, в противном случае — 0.
Далее включается веб-камера и начинается сбор данных для обучение НС на основе признаков лица (нормализованных расстояний от точки носа до точек глаз). Лицо необходимо поворачивать перед камерой, чтобы получать на вход НС разнообразные данные. Камера автоматически выключается после снятия данных с 20 кадров.
Процесс обучения запускается кнопкой Train. Данные перед этим группируются должным образом.
Желательно, чтобы чередовались данные фреймов с сигналом на выходе 1 и сигналом на выходе 0 — [1 0 1 0 1 0 …]. Иначе может произойти не обучение НС, а ее переучивание с одного состояния в другое .
Для тестирования корректности обучения включается опция Recognition и нажимается кнопка Start. Тест считается успешным, если при повороте головы появляется соответствующее сообщение.
Программный код приводится ниже:
from tkinter import * from tkinter import filedialog from tkinter import messagebox as mb import numpy as np import cv2 from mtcnn.mtcnn import MTCNN def Video(train,y): global n, nk, side detector = MTCNN() video_capture = cv2.VideoCapture(0) while True: n = n + 1 #счетчик кадров # Capture frame-by-frame ret, frame = video_capture.read() image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) result = detector.detect_faces(image) # Result is an array with all the bounding boxes detected. bounding_box = result[0]['box'] keypoints = result[0]['keypoints'] cv2.rectangle(frame, (bounding_box[0], bounding_box[1]), (bounding_box[0]+bounding_box[2], bounding_box[1] + bounding_box[3]), (0,155,255), 2) cv2.circle(frame,(keypoints['left_eye']), 3, (0,155,255), 2) cv2.circle(frame,(keypoints['right_eye']), 2, (0,155,255), 2) cv2.circle(frame,(keypoints['nose']), 3, (0,155,255), 2) cv2.circle(frame,(keypoints['mouth_left']), 3, (0,155,255), 2) cv2.circle(frame,(keypoints['mouth_right']), 3, (0,155,255), 2) cv2.line(frame,(keypoints['left_eye']),keypoints['right_eye'], (0,0,255), 1) cv2.line(frame,(keypoints['left_eye']),keypoints['nose'], (0,255,0), 2) cv2.line(frame,(keypoints['right_eye']),keypoints['nose'], (255,0,0), 2) dX = keypoints['right_eye'][0] - keypoints['left_eye'][0] dY = keypoints['right_eye'][1] - keypoints['left_eye'][1] dist_norm = np.sqrt((dX ** 2) + (dY ** 2)) dX = keypoints['left_eye'][0] - keypoints['nose'][0] dY = keypoints['left_eye'][1] - keypoints['nose'][1] dist_left = np.sqrt((dX ** 2) + (dY ** 2)) dX = keypoints['right_eye'][0] - keypoints['nose'][0] dY = keypoints['right_eye'][1] - keypoints['nose'][1] dist_right = np.sqrt((dX ** 2) + (dY ** 2)) # Normalized Features-distances input_left = dist_left/dist_norm input_right = dist_right/dist_norm X = np.array([[input_left,input_right]]) if train == True: if n <= nk: Training_data(X,y,side) print(n) else: print('Считывание входных данных завершилось') side = False break else: Recognition(X,frame,bounding_box) #print(result) # Display the resulting frame cv2.imshow('Video', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break # When everything is done, release the capture video_capture.release() cv2.destroyAllWindows() def Training_data(X,y,side): global n global X_data global y_data global X_data_new global y_data_new if side == True: # Формирование данных для первой стороны лица [1,1,1,1...] X_data = np.concatenate((X_data, X)) y_data = np.concatenate((y_data, y)) #print(X_data) #print(y_data) else: # Добавление данных для другой стороны лица c их перемешиванием [1,0,1,0...] X_data_new = np.concatenate((X_data_new, X_data[[n - 1]], X)) y_data_new = np.concatenate((y_data_new, y_data[[n - 1]], y)) #print(X_data_new) #print(y_data_new) def Training(ev): global synapses_hidden global synapses_output global X_data global y_data global X_data_new global y_data_new X_data = X_data_new y_data = y_data_new print('Выборка для обучения') X = X_data y = y_data print(X) print(y) print('Обучение началось') # обучение сети - цикл из 10000 повторений for j in range(10000): # Входной слой ( 2 входа ) l0 = X # Скрытый слой ( 3 скрытых нейрона ) l1 = 1 / (1 + np.exp(-(l0.dot(synapses_hidden)))) # Выходной слой ( 1 выходной нейрон ) l2 = 1 / (1 + np.exp(-(l1.dot(synapses_output)))) # вычисляем ошибку (используем дельта-правило) l2_delta = (y - l2) * (l2 * (1 - l2)) # получаем ошибку на скрытом слое (используем дельта-правило) l1_delta = l2_delta.dot(synapses_output.T) * (l1 * (1 - l1)) # корректируем веса от скрытых нейронов к выходу synapses_output += l1.T.dot(l2_delta) # корректируем веса от входов к скрытым нейронам synapses_hidden += l0.T.dot(l1_delta) print('Обучение закончилось') def Recognition(X,frame,bounding_box): global synapses_hidden global synapses_output global n # Входной слой ( 2 входа ) l0 = X # Скрытый слой ( 3 скрытых нейрона ) l1 = 1 / (1 + np.exp(-(l0.dot(synapses_hidden)))) # Выходной слой ( 1 выходной нейрон ) l2 = 1 / (1 + np.exp(-(l1.dot(synapses_output)))) print(n) print('Результат распознавания') print(l2) if l2 >= 0.9: # if l2[0] >= 0.9: # YES RIGHT cv2.putText(frame, str('RIGHT'), (bounding_box[0], bounding_box[1]), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), 2, lineType=cv2.LINE_AA) else: if l2 >= 0.1: # NO LEFT cv2.putText(frame, str('CENTER'), (bounding_box[0], bounding_box[1]), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), 2, lineType=cv2.LINE_AA) else: cv2.putText(frame, str('LEFT'), (bounding_box[0] + bounding_box[2], bounding_box[1]), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 2, lineType=cv2.LINE_AA) def Quit(ev): global root root.destroy() def Start(ev): global n n = 0 value = option.get() y = np.array([[0]]) if value == 1: train = True answer = mb.askyesno(title="Question", message="Right side?") if answer == True: y = np.array([[1]]) else: # Recognition train = False Video(train,y) # ОСНОВНАЯ ПРОГРАММА # инициализация глобальных переменных # инициализация случайных весов (от -1 до +1) синапсов np.random.seed(1) synapses_hidden = 2 * np.random.random((2,3)) - 1 # 2*3 - hidden слой synapses_output = 2 * np.random.random((3,1)) - 1 # 3*1 - output слой side = True # True - левая сторона, False - правая сторона n = 0 # текущий номер фрейма nk = 20 # Число фреймов для обучения за одно включение камеры X_data = np.array([[0.0,0.0]]) y_data = np.array([[0.0]]) X_data_new = np.array([[0.0,0.0]]) y_data_new = np.array([[0.0]]) # Удаляются первые элементы из массива X_data = np.delete(X_data,0,axis=0) y_data = np.delete(y_data,0,axis=0) X_data_new = np.delete(X_data_new,0,axis=0) y_data_new = np.delete(y_data_new,0,axis=0) # Interface root = Tk() panelFrame = Frame(root, height = 60, bg = 'gray') textFrame = Frame(root, height = 40, width = 400) panelFrame.pack(side = 'top', fill = 'x') textFrame.pack(side = 'bottom', fill = 'both', expand = 1) option = IntVar() R1 = Radiobutton(panelFrame, text="Training ", value = 1, var = option) R1.pack() R2 = Radiobutton(panelFrame, text="Recognition", value = 2, var = option) R2.pack() value = option.set(1) startBtn = Button(panelFrame, text = 'Start') quitBtn = Button(panelFrame, text = 'Quit') trainBtn = Button(panelFrame, text = 'Train') startBtn.bind("<Button-1>", Start) trainBtn.bind("<Button-1>", Training) quitBtn.bind("<Button-1>", Quit) startBtn.place(x = 50, y = 10, width = 40, height = 40) trainBtn.place(x = 270, y = 10, width = 40, height = 40) quitBtn.place(x = 340, y = 10, width = 40, height = 40) root.mainloop()
Программный код (вариант 2)
Эта программа позволяет сохранять для обучения данные с выбранных кадров. С помощью нее проводились исследования на Адекватность и оптимальность нейронной сети.
При запуске программы, она сразу же находится в режиме тестирования, результат которого отображается в правом верхнем углу. Однако, до обучения результат некорректный. В левом углу отображаются данные (размеры сторон треугольника), которые подаются на вход нейронной сети.
Входные данные вводятся в выборку для обучения при нажатии кнопки Save. При этом сигнал на выходе (1 или 0) задается выбором соответствующей Radio-button опции (Right или Left). После набора в списках достаточного количества данных запускается процедура обучения кнопкой Train. После завершения обучения результат тестирования отображается в правом верхнем углу уже корректно.
Диалог отслеживается в окне консоли:
Программный код приводится ниже:
import time import sys from tkinter import * from tkinter import messagebox as mb import tkinter as tk import numpy as np import cv2 from PIL import Image, ImageTk from mtcnn.mtcnn import MTCNN from numpy import exp, array, random, dot def opencvToTk(frame): #Convert an opencv image to a tkinter image, to display in canvas rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) pil_img = Image.fromarray(rgb_image) tk_image = ImageTk.PhotoImage(image=pil_img) return tk_image def mousePressed(event, data): pass def keyPressed(event, data): if event.keysym == "q": data.root.destroy() if event.keysym == "w": Save() pass def timerFired(data): pass def Save(event): global option global X global y global input_left global input_right l = input_left r = input_right X = np.concatenate((X, [[l,r]])) print ("Сигналы на входе") print (X) print ("Сигналы на выходе") value = option.get() if value == 0: y = np.concatenate((y, [[1]])) print (y) else: y = np.concatenate((y, [[0]])) print (y) print ("Следующий кадр или переходите к обучению (Train)") def Teach(event): global synapses_hidden global synapses_output global X global y print ( 'Обучение началось') # обучение сети - цикл из 10000 повторений for j in range(10000): # Входной слой ( 2 входа ) l0 = X # Скрытый слой ( 3 скрытых нейрона ) l1 = 1 / (1 + np.exp(-(l0.dot(synapses_hidden)))) # Выходной слой ( 1 выходной нейрон ) l2 = 1 / (1 + np.exp(-(l1.dot(synapses_output)))) # вычисляем ошибку (используем дельта-правило) l2_delta = (y - l2) * (l2 * (1 - l2)) # получаем ошибку на скрытом слое (используем дельта-правило) l1_delta = l2_delta.dot(synapses_output.T) * (l1 * (1 - l1)) # корректируем веса от скрытых нейронов к выходу synapses_output += l1.T.dot(l2_delta) # корректируем веса от входов к скрытым нейронам synapses_hidden += l0.T.dot(l1_delta) print ( 'Обучение закончилось') # Печать сигналов на выходе после последнего цикла обучения print ( 'Сигналы на выходе после последнего цикла обучения') print(l2) def Test(data,l,r): global synapses_hidden global synapses_output l0 = np.array([l,r]) # Скрытый слой ( 3 скрытых нейрона ) l1 = 1 / (1 + np.exp(-(l0.dot(synapses_hidden)))) # Выходной слой ( 1 выходной нейрон ) l2 = 1 / (1 + np.exp(-(l1.dot(synapses_output)))) #print('Распознавание') #print(l) #print(r) if l2 > 0.9: cv2.putText(data.frame, 'RIGHT', (500,50), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), 2,lineType=cv2.LINE_AA) else: if l2 >= 0.1: cv2.putText(data.frame, 'CENTER', (500,50), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), 2, lineType=cv2.LINE_AA) else: cv2.putText(data.frame, 'LEFT', (500,50), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 2, lineType=cv2.LINE_AA) def cameraFired(data): global input_left global input_right data.frame = cv2.GaussianBlur(data.frame, (11, 11), 0) image = cv2.cvtColor(data.frame, cv2.COLOR_BGR2RGB) result = detector.detect_faces(image) try: # Capture frame-by-frame # Result is an array with all the bounding boxes detected. bounding_box = result[0]['box'] keypoints = result[0]['keypoints'] cv2.rectangle(data.frame, (bounding_box[0], bounding_box[1]), (bounding_box[0]+bounding_box[2], bounding_box[1] + bounding_box[3]), (0,155,255), 2) cv2.circle(data.frame,(keypoints['left_eye']), 3, (0,155,255), 2) cv2.circle(data.frame,(keypoints['right_eye']), 2, (0,155,255), 2) cv2.circle(data.frame,(keypoints['nose']), 3, (0,155,255), 2) cv2.circle(data.frame,(keypoints['mouth_left']), 3, (0,155,255), 2) cv2.circle(data.frame,(keypoints['mouth_right']), 3, (0,155,255), 2) cv2.line(data.frame,(keypoints['left_eye']),keypoints['right_eye'], (0,0,255), 1) cv2.line(data.frame,(keypoints['left_eye']),keypoints['nose'], (0,255,0), 2) cv2.line(data.frame,(keypoints['right_eye']),keypoints['nose'], (255,0,0), 2) dX = keypoints['right_eye'][0] - keypoints['left_eye'][0] dY = keypoints['right_eye'][1] - keypoints['left_eye'][1] dist_norm = np.sqrt((dX ** 2) + (dY ** 2)) dX = keypoints['left_eye'][0] - keypoints['nose'][0] dY = keypoints['left_eye'][1] - keypoints['nose'][1] dist_left = np.sqrt((dX ** 2) + (dY ** 2)) dX = keypoints['right_eye'][0] - keypoints['nose'][0] dY = keypoints['right_eye'][1] - keypoints['nose'][1] dist_right = np.sqrt((dX ** 2) + (dY ** 2)) # Normalized Features-distances input_left = dist_left/dist_norm input_right = dist_right/dist_norm # Постоянно идет тестирование (даже еще до обучения) Test(data, input_left,input_right) cv2.putText(data.frame, str(input_left), (50,50), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), lineType=cv2.LINE_AA) cv2.putText(data.frame, str(input_right), (50,100), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), lineType=cv2.LINE_AA) except IndexError: gotdata = 'null' def drawCamera(canvas, data): data.tk_image = opencvToTk(data.frame) canvas.create_image(data.width / 2, data.height / 2, image=data.tk_image) def redrawAll(canvas, data): drawCamera(canvas, data) def run(width=300, height=300): global option #class Struct(object): pass #data = Struct() data.width = width data.height = height data.camera_index = 0 data.timer_delay = 100 # ms data.redraw_delay = 50 # ms # Initialize the webcams camera = cv2.VideoCapture(data.camera_index) data.camera = camera # Make tkinter window and canvas data.root = Tk() canvas = Canvas(data.root, width=data.width, height=data.height) canvas.pack() option = BooleanVar() R1 = Radiobutton(data.root, text="Right", value = 0, var = option) #R1.pack() R1.place(x = 50, y = 10, width = 50, height = 20) R2 = Radiobutton(data.root, text="Left ", value = 1, var = option) #R2.pack() R2.place(x = 50, y = 30, width = 50, height = 20) option.set(0) #print (value) btn = Button(data.root, #родительское окно text="Save face", #надпись на кнопке width=30,height=5, #ширина и высота bg="white",fg="black") btn.bind("<Button-1>", Save) btn1 = Button(data.root, #родительское окно text="Train", #надпись на кнопке width=30,height=5, #ширина и высота bg="white",fg="black") btn1.bind("<Button-1>", Teach) btn.place(x = 110, y = 10, width = 70, height = 40) btn1.place(x = 200, y = 10, width = 70, height = 40) # Basic bindings. Note that only timer events will redraw. data.root.bind("<Button-1>", lambda event: mousePressed(event, data)) data.root.bind("<Key>", lambda event: keyPressed(event, data)) # Timer fired needs a wrapper. This is for periodic events. def timerFiredWrapper(data): # Ensuring that the code runs at roughly the right periodicity start = time.time() timerFired(data) end = time.time() diff_ms = (end - start) * 1000 delay = int(max(data.timer_delay - diff_ms, 0)) data.root.after(delay, lambda: timerFiredWrapper(data)) # Wait a timer delay before beginning, to allow everything else to # initialize first. data.root.after(data.timer_delay, lambda: timerFiredWrapper(data)) def redrawAllWrapper(canvas, data): start = time.time() # Get the camera frame and get it processed. _, data.frame = data.camera.read() cameraFired(data) # Redrawing code canvas.delete(ALL) redrawAll(canvas, data) # Calculate delay accordingly end = time.time() diff_ms = (end - start) * 1000 # Have at least a 5ms delay between redraw. Ideally higher is better. delay = int(max(data.redraw_delay - diff_ms, 5)) data.root.after(delay, lambda: redrawAllWrapper(canvas, data)) # Start drawing immediately data.root.after(0, lambda: redrawAllWrapper(canvas, data)) # Loop tkinter data.root.mainloop() # Once the loop is done, release the camera. print("Releasing camera!") data.camera.release() # ОСНОВНАЯ ПРОГРАММА detector = MTCNN() class Struct(object): pass data = Struct() var_1 = 0 X = np.array([[0.0,0.0]]) y = np.array([[0.0]]) # Удаляются первые элементы из массива X = np.delete(X,0,axis=0) y = np.delete(y,0,axis=0) #y = np.array([]) input_left = 0.6 input_right = 1.0 # инициализация случайных весов (от -1 до +1) синапсов np.random.seed(1) synapses_hidden = 2 * np.random.random((2,3)) - 1 # 2*3 - hidden слой synapses_output = 2 * np.random.random((3,1)) - 1 # 3*1 - output слой print("Подготовьте данные для обучения!") if __name__ == "__main__": run(700, 600)
Далее см. статью Адекватность и оптимальность нейронной сети для распознавания поворота головы
Полезные ссылки:
- 112-opencv-tutorial/opencvTkinterTemplate.py
- Введение в машинное обучение
- Персептрон Розенблатта — машина, которая смогла обучаться
- Простая нейросеть на JavaScript: Распознавание рисунков
- Распознавание лиц на основе OpenCV для C++
- Распознавание лиц. 3D-реконструкция ASM модели
- Идентификация по множеству признаков. Основы
- Идентификация по множеству признаков при помощи нейросети
- Main concepts behind Machine Learning
- Добавить массив NumPy к массиву NumPy
- Radiobutton и Checkbutton. Переменные Tkinter
- Speedy Computer Vision Pipelines using Parallelism
- Введение в pandas: анализ данных на Python
- Краткое руководство. Клиентская библиотека API Распознавания лиц для Python
- Распознаем лица на фото с помощью Python и OpenCV
- Python: распознавание объектов в реальном времени
Автор: Николай Свирневский