我正在努力让我的NN认出“快乐”和“悲伤”的面孔,用20x20画布手绘。我使用400个输入图层单元,100个隐藏图层单元和2个输出单元(快乐/悲伤)。隐藏和激活的激活功能输出层是sigmoid。
我正在逐步训练神经网络,手动绘制一张脸,选择它是快乐还是悲伤,并将训练样本喂给神经网络。此外,在我绘制时,程序会动态显示NN输出。
问题在于,只要我连续添加一堆快乐面孔,“快乐”的输出就会提升到接近1.然而,如果我开始添加悲伤的面孔,输出会变为happy = 0.0241 ......伤心= 0.9988 ......
有时候,两个输出都会上升到几乎一个(快乐= 0.99 /悲伤= 0.99)。
它似乎应该以这种方式工作,但为了测试神经网络,我开始在画布的上半部分绘制HAPPY面部,在下半部分绘制SAD面部。同样的事情发生了(输出倾向于最新的样本),但是我添加了50个训练样例,输出似乎对我在下半部/上半部分的绘画没有反应。
我不明白我是正确构建NN还是正确输入数据(它只是一个400大小的数组,有0.01(白色)或0.99(黑色))。
如何防止此行为?
神经网络课程:
import scipy.special
import numpy
class NeuralNetwork:
def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
# set number of nodes in each input, hidden, output layer
self.inodes = inputnodes
self.hnodes = hiddennodes
self.onodes = outputnodes
# learning rate
self.lr = learningrate
# activation function
self.activation_function = lambda x: scipy.special.expit(x)
# link weight matrices, wih and who
self.wih = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))
self.who = numpy.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes, self.hnodes))
pass
# train the neural network
def train(self, inputs_list, targets_list):
# convert inputs list to 2d array
inputs = numpy.array(inputs_list, ndmin=2).T
targets = numpy.array(targets_list, ndmin=2).T
# calculate signals into hidden layer
hidden_inputs = numpy.dot(self.wih, inputs)
# calculate the signals emerging from hidden layer
hidden_outputs = self.activation_function(hidden_inputs)
# calculate signals into final output layer
final_inputs = numpy.dot(self.who, hidden_outputs)
# calculate signals emerging from final output layer
final_outputs = self.activation_function(final_inputs)
# error is the (target - actual)
output_errors = targets - final_outputs
# hidden layer error is the output_errors, split by weights, recombined at hidden nodes
hidden_errors = numpy.dot(self.who.T, output_errors)
# update the weights for the links between the hidden and output layers
self.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)),
numpy.transpose(hidden_outputs))
# update the weights for the links between the input and hidden layers
self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)),
numpy.transpose(inputs))
pass
def query(self, inputs_list):
# convert inputs list to 2d array
inputs = numpy.array(inputs_list, ndmin=2).T
# calculate signals into hidden layer
hidden_inputs = numpy.dot(self.wih, inputs)
# calculate the signals emerging from the hidden layer
hidden_outputs = self.activation_function(hidden_inputs)
# calculate signals into final output layer
final_inputs = numpy.dot(self.who, hidden_outputs)
# calculate the signals emerging from final output layer
final_outputs = self.activation_function(final_inputs)
return final_outputs
主要代码:
from tkinter import *
import numpy
# scipy.special for the sigmoid function expit()
import scipy.special
# library for plotting arrays
import matplotlib.pyplot
from nn import *
root = Tk()
frame = Frame(root)
w = Canvas(frame, width=400, height=400, background="green")
w.pack()
canvasRectangles = []
for i in range(20):
ls = []
for k in range(20):
x = 20*i
y = 20*k
ls.append(w.create_rectangle(x,y,x+20,y+20,fill="white"))
canvasRectangles.append(ls)
label = Label(frame,text='Number pressed: N/A')
label.pack()
hdnLayer1Label = Label(frame,text="Hidden Layer 1",justify=LEFT,wraplength=300)
hdnLayer1Label.pack()
outLayerLabel = Label(frame,text="Output Layer",justify=LEFT,wraplength=300)
outLayerLabel.pack()
def clearCanvas():
for i in range(20):
for k in range(20):
w.itemconfig(canvasRectangles[i][k],fill="white")
def key(event):
if event.char is 'r':
clearCanvas()
else:
if event.char is '1':
label.config(text="SMILE: Happy")
if event.char is '2':
label.config(text="SMILE: Sad")
global number
number = event.char
def initNN():
input_nodes = 400
hidden_nodes = 100
output_nodes = 2
learning_rate = 0.3
global n
n = NeuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
def queryNN(rectangles):
unscaledInputs = getRectangleValues(rectangles)
arr = numpy.array(unscaledInputs)
scaledInputs = scaleInputs(arr)
res = n.query(scaledInputs)
return res
def trainNN(rectangles, desiredOuts):
inputs = getRectangleValues(rectangles)
arr = numpy.array(inputs)
# Scale the inputs
scaledInputs = scaleInputs(arr)
global n
n.train(scaledInputs, desiredOuts)
pass
def getRectangleValues(rectangles):
rectvals = []
for col in range(20):
for row in range(20):
if w.itemcget(rectangles[col][row], "fill") == "black":
rectvals.append(0)
else:
rectvals.append(1)
return rectvals
def tab(event):
desiredOuts = [0, 0]
if number is '1':
desiredOuts[0] = 1
print("desiredSmile= HAPPY")
if number is '2':
desiredOuts[1] = 1
print("desiredSmile= SAD")
print(desiredOuts)
trainNN(canvasRectangles, desiredOuts)
clearCanvas()
def draw(event):
x = event.x
y = event.y
if x <= 400 and y <= 400 and x >= 0 and y >= 0:
squarex = int(translate(x, 0, 400, 0, 20))
squarey = int(translate(y, 0, 400, 0, 20))
if not squarex is 20 or not squarey is 20:
w.itemconfig(canvasRectangles[squarex][squarey], fill="black")
outLayerLabel.config(text="Output: " + repr(queryNN(canvasRectangles)))
def translate(value, leftMin, leftMax, rightMin, rightMax):
# Figure out how 'wide' each range is
leftSpan = leftMax - leftMin
rightSpan = rightMax - rightMin
# Convert the left range into a 0-1 range (float)
valueScaled = float(value - leftMin) / float(leftSpan)
# Convert the 0-1 range into a value in the right range.
return rightMin + (valueScaled * rightSpan)
def scaleInputs(unscaledins):
return (numpy.asfarray(unscaledins) / 1.0 * 0.99) + 0.01
initNN()
w.bind("<Button-1>", draw)
w.bind("<B1-Motion>", draw)
frame.bind("1",key)
frame.bind("2",key)
frame.bind("r", key)
frame.bind("<Tab>", tab)
frame.pack()
frame.focus_set()
'root.after(0,doWork)'
root.mainloop()
答案 0 :(得分:0)
如果其他人有类似的问题,我通过降低画布分辨率(从20x20到7x7)来解决它。我想这么高的分辨率需要更多的训练样本。 此外,我制作了一套训练集,并经过几次迭代(大约8个时期为我做了诀窍)。
解决方案很简单:如果您的输入更复杂,则需要更多培训。