神经网络
https://www.bilibili.com/video/BV1Y64y1Q7hi?spm_id_from=333.999.0.0
(我只能说这个up讲的是真滴好,兄弟们去一键三连一下)
上一次介绍了感知机,神经网络中的一个单元。这次来简单介绍一下神经网络到底是什么。
激活函数的改变
对于上一次感知机只能处理一个二分类的问题,不能处理异或问题,在神经网络这儿都做出了巨大的改变。
首先激活函数的改变(变成了sigmod函数)使得神经网络不止判断一个事物的对错,还能判断一个事物的好坏,这就很神奇。
sigmod函数
现在随着输出,感知机不是只会返回 0 1,现在返回(0,1)产生了巨大差距,从而也产生了一个新的东西。阈值,它反映的是,这个感知机反馈整个输入是正类的难度,如果阈值越小,这个感知机被激活,或者说这个感知机表现为正类就更容易,如果阈值越大就反之。
损失函数
来讲解一下什么是损失函数(为了梯度下降做铺垫)。准确的说损失函数是为了衡量我们训练的模型好坏,好坏的标准就是损失函数的大小。损失函数的值越小,那说明训练的模型越好,损失函数越大,说明训练的模型效果越差。(暂时先这么理解,其实还有过拟合等问题)。
常用的方法
- 最小二乘法
- 最大似然估计
- 交叉熵
最小二乘法
最小二乘法也是我们最直观,脑子里第一个蹦出来的思路。当了解需要评估一个模型的好坏,直接的想法一定是直接拿来与现实的结果进行对比,也就是
这个结果非常的直观,可以一下子评估出来。但是这对我们后面的梯度下降非常不友好,因为绝对值往往带来的问题是不可导。于是我们转换一下思路
这样就可导了,且1/2是为了最后求导之后与带来的2相抵消。
最大似然估计
最大似然估计的思想我觉得是和神经网络特别相似的。比如都是从现在的结果去推原来的模型。神经网络是给大量的数据去构造神经网络心中描述最完美的模型,而最大似然估计就是按这个思路来的
现在黄色代表我们的模型,这个绿色代表了实际的结果。投了10次硬币,现在的结果是7正3反。现在想推出这个模型是什么。
得到的情况可能是很多的,黄色图中的三种模型都是有可能的。但是每一个模型的概率是不相同的。
经过计算第二个模型的概率是最大的。这就是最大似然估计法。难道我们根据这个就能定义这个模型就一定是原来的模型吗,这是不一定的,只是概率最大而已。
其实到这里,大概理解他的意思就行,最后还都是调api所以这之后我就没有深究,包括交叉熵我也没深究
反向传播
梯度下降法是反向传播的一种。我们理解的正向传播,就是输入通过一层一层的感知机,最后到输出的过程。那反向传播就是从输出开始,逆着,一层一层的调整参数。反向传播的形式有很多种,梯度下降法是里面最经典,也是最重要的一种。
举一个反向传播的例子,这个是不严谨的,只适用于理解
- 蓝色的就是输出感知机。这个感知机由三部分组成 W A B,分别代表 系数,输入和偏移量。其中系数和偏移量可以在当前这轮进行修改,但是输入代表的是上一层的输出,这个只有修改上一层才能行。
- 绿色的代表我们的损失函数,我们希望这个绿色的饼越小越好
在进行第一次计算之后,可以把a向前传播。不是平均传播,对这个感知机影响比较大的,改动的权重就多一些,影响小的,改动的就少一些。
按照这个原理不停的向前传播,传播到第一层的时候,只能修改参数不能修改输入,因为输入是固定的。
梯度下降
首先要明确,梯度是一个函数增长最快的方向。也就是说它的反方向就是函数降低最快的方向。
在神经网络中,就是这样一个形式。在方向上乘上一个足够小的量。但是值得注意的是a作为本层的输入是上一层的输出,他的改变是依靠上一层输出的。
套用上梯度公式就是这样
对于梯度下降,我们来讲解一下他的代码部分(此处参考博客https://www.jianshu.com/p/7251b03847f4)
梯度下降是一个不断迭代的过程
这篇博客前面的例子都是符合我理解的
f(x,y) = 3x^2 + 4y^2 + 5 对于这个函数
dx = 6x dy = 8y
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# init some data
x_data = np.arange(-4, 4, 0.25)
y_data = np.arange(-4, 4, 0.25)
f_data = np.square(x_data)*3 + np.square(y_data) * 4 + 5
X, Y = np.meshgrid(x_data, y_data)
Z = np.sqrt(f_data)
fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='rainbow')
plt.ion()
plt.show()
start_x = 10
start_y = 10
step = 0.01
current_x = start_x
current_y = start_y
current_f = 3 * current_x * current_x + 4 * current_y + 5
print("(loop_count, current_x, current_y, current_f)")
for i in range(100):
print(i, current_x, current_y, current_f)
### derivatives of x and y
derivative_f_x = 6 * current_x
derivative_f_y = 8 * current_y
### update x, y
current_x = current_x - step * derivative_f_x
current_y = current_y - step * derivative_f_y
### current f
current_f = 3 * current_x * current_x + 4 * current_y + 5
ax.scatter(np.meshgrid(current_x), np.meshgrid(current_y), np.sqrt(current_f))
plt.pause(0.1)
current_x = current_x - step * derivative_f_x
current_y = current_y - step * derivative_f_y
这两句代码尤为关键,其实我们看出每一次迭代就是x和y向着各自的偏导方向走了一个step的距离
但是对于一个函数
Wx + b这样子的呢
之前我们是确定系数,然后沿着偏导的方向走,可是现在我们是要确定一条线或者一个平面,能够最大程度的去拟合我们给出所有数据点。
现在是坐标系中给出一些散点,然后希望用找到一条线可以最大程度拟合这些点
这句话真的是点醒了我
我现在是在找一个w和b,可以最大程度的去拟合这些点对吗。
我们可以设置我们自己的损失函数,在这里我们把cost_function = Least squares(最小平方法),
当做损失函数,也就是所有点到这条线的距离和,这个距离和越小越好
这个是我们的核心思想
import numpy as np
import matplotlib.pyplot as plt
m = 20
# init some data
x_data = np.arange(1, m + 1).reshape([m, 1])
y_data = x_data*3 + 5
# for polt picture
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.scatter(x_data, y_data)
plt.ion()
plt.show()
w1 = 0
b1 = 0
step = 0.01
def cost_function(y_prediction):
return 1.0/(2 * m) * np.sum(np.square(y_prediction - y_data))
y_prediction = x_data * w1 + b1
ax.plot(x_data, y_prediction, 'black', lw=3)
print("(i, cost_function)")
for i in range(250):
print(i, cost_function(y_prediction))
derivative_f_w1 = 1.0/m * np.sum(np.multiply(y_prediction - y_data, x_data))
derivative_f_b1 = 1.0/m * np.sum(y_prediction - y_data)
w1 = w1 - step * derivative_f_w1
b1 = b1 - step * derivative_f_b1
y_prediction = x_data * w1 + b1
try:
ax.lines.remove(lines[0])
except Exception:
pass
lines = ax.plot(x_data, y_prediction, 'r-', lw=3)
plt.pause(0.1)
print('w1:', w1, 'b1:', b1)