目录
一、引言
二、隐藏层
三、深度学习(炼丹)
三、编程实验
四、总结
五、往期内容
大自然往往是变幻莫测,喜怒无常。在一次地球环境巨变之后,小蓝所在的海底生物们也经历了巨大的进化。豆豆变得不再是简单的越大或者越小越可能有毒,而是在某个大小范围内有毒,而某些范围内无毒,比如这样。此时,不论是不加激活函数的预测模型,还是加了激活函数的预测模型,似乎都开始变得无能为力了。此刻新的豆豆的毒性却变得忽大忽小,想要预测它们,不再是像以前一样单调的函数。
那么,如何让预测模型能够产生这种山丘一样的曲线?是时候让神经元形成一个网络!我们唯一做的事情就是多添加了两个神经元,并把输入分别送入到这两个神经元进行计算,再把计算的结果送入到第三个神经元计算最后输出。
我们用可视化工具调节一下这三个神经元的参数。最后得到这样的一个效果,分类成功。
所以为什么会这样?其实很简单,对于第一个和第二个神经元,先通过线性函数计算,再通过激活函数得到最终的输出,而利用梯度下降算法,最终的输出一定可以被调节成为现在这个样子。
把这两个神经元的最终输出作为第三个神经元的输入,先通过第三个神经元的线性函数计算,乘上权重,再通过激活函数并利用梯度下降算法,把最终的输出调节成为这个样子。
也就是说,把输入分为两个部分,然后分别对这两个部分进行调节,然后再送入最后一个神经元,让整体的神经网络形成一个单调性、不唯一的多变函数,从而具备了解决更加复杂问题的能力。
中间这些新添加了神经元节点,也称之为隐藏层。
可以看出来,这是隐藏层的存在才让神经网络能够在复杂的情况下仍旧working。显而易见的是,隐藏层的神经元数量越多,就可以产生越复杂的组合,解决越复杂的问题,当然计算量也随之越来越大。我们已经横向的在神经网络上增加了神经元,形成了一层隐藏层,而在之后的课程中,我们会纵向的不断添加神经元,产生更深的隐藏层输入,通过这些隐藏层被一层又一层的不断抽象和理解,提 取出微妙的特征,从而让神经网络变得更加强大和智能,而这些隐藏层也就是神经网络为什么working的本质。
当我们建立一个复杂程度恰当的神经网络,经过充分的训练之后,网络中的各个神经元的参数被调节成为不同的值,这些功能单一的神经元连接组合出来的整体就可以近似出一个相当复杂的函数:
最终变成什么样则是根据我们采集的训练数据决定。而我们采集的训练数据越充足,那么最后训练得到的模型也就能够越好的去预测新的问题。因为越充足的训练数据就在越大程度上蕴藏的问题的规律和特征,新的问题数据也就越难以逃脱这些规律的约束。所以我们总是说,机器学习神经网络的根基是海量的数据,一个训练之后拟合适当的模型,进而在遇到新的问题数据的时候,也能大概率产生正确的预测,我们把这个现象称这为模型的泛化,模型的泛化能力也就是神经网络追求的核心问题。
我们经常听到深度学习,其中深度二字其实并没有什么特别的奥义,只是指一个神经网络中纵向的隐藏层比较多,换句话说很深。我们一般把隐藏层超过三层的网络也就称之为深度神经网络。这也是深度学习中广受诟病的地方,隐藏层的神经元在理解什么,提取什么都太过微妙。虽然我们对大致的结果有所把握,但却很难用精确的数学去进行描述。我们能做的也只有设计一个网络,搜索数据,然后充分的训练。如果得到的预测效果好,我们就会说它起作用了,如果不好,那也只能说搞错了调教参数再来一遍。
所以很多人戏称深度学习是炼丹。确实,道士把原材料放入八卦炉开火炼丹,最后得到的仙丹可能让人长生不老,也可能让人一命呜呼。炼丹过程中八卦炉里发生的微妙事情,道士也是不而知的,虽然是他设计的炼丹的一切。
1.豆豆的毒性数据生成代码dataset.py
import numpy as np
def get_beans(counts):
xs = np.random.rand(counts)*2
xs = np.sort(xs)
ys = np.zeros(counts)
for i in range(counts):
x = xs[i]
yi = 0.7*x+(0.5-np.random.rand())/50+0.5
if yi > 0.8 and yi < 1.4:
ys[i] = 1
return xs,ys
2.一个隐藏层神经网络代码one_hidden_layer_net.py
np.random.rand()随机化初始值
import dataset #调用dataset库
from matplotlib import pyplot as plt #调用matplotlib库的pyplot
#import matplotlib.pyplot as plt
import numpy as np
m=100
xs,ys=dataset.get_beans(m) #获取100个豆子数据
#配置图像,坐标信息
plt.title("Size-Toxicity Function",fontsize=12)#设置图像名称
plt.xlabel("Bean Size")#设置横坐标的名字
plt.ylabel("Toxicity")#设置纵坐标的名字
plt.scatter(xs,ys) #画散点图
#建立sigmoid函数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
#设置参数
# 第一层
# 第一个神经元
# 第几个输入和这层的第几个神经元_第几层
# 偏置项b2_1指的是第1层,第2个偏置项
# np.random.rand()随机化初始值
w11_1 = np.random.rand()#第1层的第1个神经元的权值
b1_1 = np.random.rand() #第1层的第1个神经元的偏置项
# 第二个神经元
w12_1 = np.random.rand()
b2_1 = np.random.rand() #第1层的第2个神经元的偏置项
# 第二层
w11_2 = np.random.rand()
w21_2 = np.random.rand()
b1_2 = np.random.rand() #第2层的第1个神经元的偏置项
# 建立前向传播函数,加入激活函数
def forward_propgation(xs):
z1_1 = w11_1 * xs + b1_1
a1_1 = sigmoid(z1_1)
z2_1 = w12_1 * xs + b2_1
a2_1 = sigmoid(z2_1)
#a1_2指的是第2层第1个神经元的输出
z1_2 = w11_2 * a1_1 + w21_2 * a2_1 + b1_2
a1_2 = sigmoid(z1_2)
return a1_2, z1_2, a2_1, z2_1, a1_1, z1_1
#接收返回值
a1_2, z1_2, a2_1, z2_1, a1_1, z1_1 = forward_propgation(xs)
plt.plot(xs, a1_2)
plt.show()
#反向传播
for _ in range(5000):#调整5000次全部,0-99的整数,用range 函数进行for循环
for i in range(100):#调整1次全部,可能会导致线不拟合
x=xs[i];
y=ys[i];
#先进行一次前向传播输入
a1_2, z1_2, a2_1, z2_1, a1_1, z1_1 = forward_propgation(x)
# 反向传播
# 误差代价e
e = (y - a1_2) ** 2
####
deda1_2 = -2 * (y - a1_2)
da1_2dz1_2 = a1_2 * (1 - a1_2)
dz1_2dw11_2 = a1_1
dz1_2dw21_2 = a2_1
dedw11_2 = deda1_2 * da1_2dz1_2 * dz1_2dw11_2
dedw21_2 = deda1_2 * da1_2dz1_2 * dz1_2dw21_2
dz1_2db1_2 = 1
dedb1_2 = deda1_2 * da1_2dz1_2 * dz1_2db1_2
####
dz1_2da1_1 = w11_2
da1_1dz1_1 = a1_1 * (1 - a1_1)
dz1_1dw11_1 = x
dedw11_1 = deda1_2 * da1_2dz1_2 * dz1_2da1_1 * da1_1dz1_1 * dz1_1dw11_1
dz1_1db1_1 = 1
dedb1_1 = deda1_2 * da1_2dz1_2 * dz1_2da1_1 * da1_1dz1_1 * dz1_1db1_1
dz1_2da2_1 = w21_2
da2_1dz2_1 = a2_1 * (1 - a2_1)
dz2_1dw12_1 = x
dedw12_1 = deda1_2 * da1_2dz1_2 * dz1_2da2_1 * da2_1dz2_1 * dz2_1dw12_1
dz2_1db2_1 = 1
dedb2_1 = deda1_2 * da1_2dz1_2 * dz1_2da2_1 * da2_1dz2_1 * dz2_1db2_1
# alpha为学习率
alpha = 0.03
w11_2 = w11_2 - alpha * dedw11_2
w21_2 = w21_2 - alpha * dedw21_2
b1_2 = b1_2 - alpha * dedb1_2
w12_1 = w12_1 - alpha * dedw12_1
b2_1 = b2_1 - alpha * dedb2_1
w11_1 = w11_1 - alpha * dedw11_1
b1_1 = b1_1 - alpha * dedb1_1
if _ % 100 == 0: #控制绘图时间,把绘图频率降低100倍
# 绘制动态
plt.clf() # 清空窗口
plt.scatter(xs, ys)
a1_2, z1_2, a2_1, z2_1, a1_1, z1_1 = forward_propgation(xs)
plt.xlim(0,2) #plt.xlim()函数限制x轴范围
plt.ylim(0,1.1) #plt.ylim()函数限制y轴范围
plt.plot(xs, a1_2)
plt.pause(0.01) # 暂停0.01秒
得出图像
本节课介绍了隐藏层,我们知道通常预测函数不会是简单的单调函数,我们就需要添加隐藏层来解决复杂函数。隐藏层的神经元数量越多,就可以产生越复杂的组合,解决越复杂的问题,当然计算量也随之越来越大。如果隐藏层超过三层的网络,就可以称之为深度神经网络。
引言:来一场人工智能的奇妙冒险吧~
1.一元一次函数感知器:如何描述直觉
2.方差代价函数:知错
3.梯度下降:能改
4.反向传播:能改
5.激活函数:给机器注入灵魂
6.隐藏层:神经网络为什么working
7.高维空间:机器如何面对越来越复杂的问题
8.初识Keras:轻松完成神经网络模型搭建
9.深度学习:神奇的DeepLearning
10.卷积神经网络:打破图像识别的瓶颈
11. 卷积神经网络:图像识别实战
12.循环:序列依赖问题
13.LSTM网络:自然语言处理实践
14.机器学习:最后一节课也是第一节课
视频链接:https://pan.baidu.com/s/1G_52Qg3zf4asxVaAbnZukA?pwd=jtm6
可视化工具链接:https://pan.baidu.com/s/1D_z8tqc7lMm3ti1wsJRMsw?pwd=b7zj
可视化工具包含:2层神经网络调节工具