神经网络
模仿人类的神经细胞运作原理而形成一种网络模型,就是神经网络模型
它由输入层,隐含层(隐藏层),输出层组成,每层都会有大于等于1个神经元(即图中的圆圈)。
每层的神经元都会通过线进行连接,连接方式为全连接(例:第一层的任意一个点和第二层的点全部点连接起来)。
(1)输入层:用于向神经网络输入数据,通常只有一层
(2)隐含层:用于进行计算,通常有多个层
(当隐含层足够多时,可称该网络为深度神经网络)
(感知机模型就是隐含层只有0层且输出层只有一个神经元的神经网络模型)
(3)输出层:用于神经网络输出结果,通常只有一层
直观的理解,神经网络就像是一个函数,给予输入,得到输出(例如函数 y = 2x ,输入1,得到2)
而神经网络通常是用来解决当函数体写不出来的情况。
举个例子,输入身高(x1),体重(x2),得出你的性别(y),y = f(x1,x2)这种函数是写不出来的,而神经网络可以学习出来,具体后面会讲。
感知机模型
什么是感知机模型?
它是由输入层和输出层组成,由于只有两层,可以说它是最简单的神经网络模型了
该图:
(1)没有隐含层,黄色圆圈就是输出层(只有一个神经元)
(2)输入层(蓝色圆圈)有三个输入神经元
(3)计算公式: y = w1 * x1 + w2 * x2 + w3 * x3 (w1,w2,w3是随机初始化得到的)
(4)断依据: 设定一个阈值b
如果y >= b ,那么网络输出1;否则,输出0
(5)因此,整个感知机可以写成:
h = 0 ,w1 * x1 + w2 * x2 + w3 * x3 < b
h = 1 ,w1 * x1 + w2 * x2 + w3 * x3 >= b
(6)整个网络好比输入了身高(x1),年龄(x2),体重(x3),得出结果性别(当性别为男时,h为1;当性别为女时,h为0),但w1,w2,w3是随机数来的,因此该网络其实不具备得出正确性别的功能,要想得出正确的性别,就要更新w1,w2和w3的值。这时需要用到梯度下降法。
反向传播(梯度下降)
假设:
1.有一个男人:身高1.8m,年龄30,体重70kg,
2.也就是说当 x1 = 1.8,x2 = 30,x3 = 70时,应该是要输出就是 h = 1 ,这个应该的输出我们叫真实值,或者标签。
3.但网络的输出却是0,这个网络的输出值成为预测值
4.这时预测值和真实值存在差别 = 1 - 0 = 1 ,但我们不能就这样简单的相减,为了能达到更新的效果,我们通常使用均方误差
5.均方误差cost =(真实值 - 预测值)²
6.为什么要用均方误差,而不是直接相减,请看下图。当直接相减时,函数是一条直线,没有最小值,当使用均方误差时,函数呈现一个碗状,存在最小值,而当均方误差最小的时候,就是真实值和预测值差别最小的时候。
7.该图是假设只有一个w作为自变量,cost作为因变量
8.梯度下降法就好比爬山,如图中的小人,站在斜坡上,根据自己所处位置的倾斜程度,向低处走。
9.梯度下降法更新w值的公式:w = w + α * d(w)式中 α 是学习率(即爬山的每一步的大小,可以小步走,也可以跨大步),d(w)是当前所在位置的导数(即爬山的方向,关于求导的知识可自行学习,因为用代码实现的时候并不需要我们去计算)
10.关于α学习率的大小选择:如果太小,每一步就会太小,因此爬山会很慢;如果太大,会一步从一个山头跨越到另一个山头,从而走不到最低点。而α的大小是要不断测试才知道的。
感知机模型代码
这份代码是用tensorflow写的,我会进行适当的解释。因此不太懂tensorflow的需要自行学习
这个代码是用感知机实现 and(与)计算
tensorflow是先创建一个网络,我们称之为图,然后再启动这个网络(图)。
import tensorflow as tf #导入tensorflow包
import numpy as np #导入numpy包
#data是四组输入和真实值的组合(例子:[0,1,0,0]中前三个数字 0 1 0 是输入,最后的0是真实值)
data = [[1,1,1,1],[1,0,0,0],[0,1,0,0],[0,0,0,0]]
#----------------------------开始创建图------------------------------------
#tf.placeholder是指先创建一个空的模型,之后再填入数据
x = tf.placeholder(tf.float32,([1,3])) #输入层是一行散列的矩阵
real = tf.placeholder(tf.float32,([1,1])) #真实值是一个一行一列的矩阵
#tf.Variable 是指变量,之后对图进行训练时只有变量会发生变化
w = tf.Variable(tf.random.normal([3,1])) #w(权重)是一个三行一列的矩阵
#tf.add(a,b)--> a + b tf.matmul(a,b)--> 矩阵a,b相乘
y = tf.add(tf.matmul(x,w)) #y(预测值)的计算方式
#tf.pow(a,b)-->a的b次方 tf.subtract(a,b)--> a - b
cost = tf.pow(tf.subtract(y,real),2) #均方误差的计算 相当于 (y - real)²
# 使用梯度下降法进行训练 学习率为0.1 目标是最小化 cost(均方误差)
train = tf.train.GradientDescentOptimizer(0.1).minimize(cost)
init = tf.global_variables_initializer() #有变量时,就要对变量进行初始化
#----------------------------创建图完毕------------------------------------
#----------------------------开始启动图------------------------------------
sess = tf.Session() #启动图
sess.run(init) #启动初始化
#训练100次
for j in range(100):
for i in range(len(data)):
#使用run进行训练,对创建图中使用placeholder创建的元素进行数据填入
#如下,x的填入值是np.array([[data[i][0],data[i][1],data[i][2]]])
sess.run(train,feed_dict={x:np.array([[data[i][0],data[i][1],data[i][2]]])
,real:np.array([[data[i][3]]])})
#输出cost(均方误差),方便查看效果
print(sess.run(cost,feed_dict={x:np.array([[data[i][0],data[i][1],data[i][2]]])
,real:np.array([[data[i][3]]])}))
print('w:',sess.run(w)) #输出w(权重)
result = [sess.run(y,feed_dict={x:np.array([[1,1,1]])}),
sess.run(y,feed_dict={x:np.array([[1,0,0]])}),
sess.run(y,feed_dict={x:np.array([[0,1,0]])}),
sess.run(y,feed_dict={x:np.array([[0,0,0]])})]
#设置阈值0.5,大于等于0.5的就当作是1,否则为0
for i in range(len(result)):
if result[i] >= 0.5:
result[i] = 1
else:
result[i] = 0
print('1 and 1',result[0])
print('1 and 0',result[1])
print('0 and 1',result[2])
print('0 and 0',result[3])
sess.close() #记得关闭
#----------------------------关闭图------------------------------------