开放实验作业
1.sigmoid函数与tanh函数的梯度消失:
写出函数表达式:
sigmoid函数:
tanh函数:
对两函数进行求导可以得到:
以sigmoid函数导数的图像为例:
令,当z的取值较大时,会发现两个函数的导数都会趋于0,这使得神经网络反馈进行梯度下降时十分缓慢,不利于权重的更新。举个一元多层神经网络的例子:
根据链式法则得到求导公式:
可见最终算出的权重会很小
解决办法:
1.使用ReLU函数: ReLU函数的表达式为:
2.ReLU函数的优点与局限性,以及部分改进
ReLU函数优点:
1.在进行梯度下降时不会受到x值的影响,即梯度消失的情况不会存在。
2.输入一个阈值便可以得到一个激活值,无需进行复杂的运算。
局限性:
在训练的过程中,有一部分z取值小于0时,对应神经元将不会被激活,也就不会参与到反馈中。当训练的神经元有很多时,很多神经元会“坏死”掉。
改进:
当时,并不令ReLU函数值为0,而是,这使得负轴的信息不会全部丢失。
3.多层感知机的平方误差以及交叉熵函数:
平方误差函数:对于隐含层和输出层神经元,输入值为y'k,实际预测值为yk,则累计平方误差为:
交叉熵函数:属于输入向量,得到预测值后,交叉熵损失函数为:
其中,代表输出神经元的个数。当有个训练数据时,交叉熵函数写成:
当训练集与测试集的正比例出现不一致时,可以假设系数,如果正样本以的比例进行抽样,负样本以的比例进行抽样,新的函数可写为:
4.损失函数比较:
平方误差损失函数:在学习率一定的情况下,平方误差损失函数的梯度会随着目标的接近而减小,因此在最后的训练过程中会取到更好效果。这类函数适用于局外点不太多的情况,当存在部分点与目标值偏差较大时,使用平均绝对误差函数会更好。
交叉熵损失函数:函数值越小,预测值与实际值相同的概率越接近。该损失函数对正确的结果较为看中,例如当预测结果为,实际结果为时,交叉熵函数值为,因此,该损失函数更多会应用于分类问题。相比较而言,平方误差损失函数应用于回归问题更好,因为他能更多照顾到错误的预测,并进行修正。
5.模型的方差与偏差关系:
模型的偏差较大时会出现欠拟合状态,模型的方差较大时会出现过拟合状态。
应用网上的一个简单图片:
当模型开始训练时,注意到的细节较少,训练出的每个预测值都会与真实值有一定差距,这时会出现偏差较大的情况。当训练时间过长,出现过拟合的情况时,输入一组数据,因模型很复杂,只能代表训练的数据而代表不了所有数据,所以得到的结果可能与实际值差别很大,即方差较大。
6.解决模型过拟合与欠拟合:
6.1.解决模型的过拟合:
1.增加一个正则化因子,在模型预测时,目标损失函数可改写为:
其中被称之为惩罚项,为大于0的常数,有不同的表示方法,取其中一种:
在此情况下,当计算下降梯度时,表达式变为:
这样的话,权重更新时原有的权重因子影响变小,权重本身会减小到比以前更小的值,避免了梯度“一家独大”的现象。
2.适当减少分类时的物品属性或回归时的多项式最高项次数。
3.在深度神经网络学习时,可以适当让部分神经元“坏死”,每次坏死的神经元随机。我认为这种方法在神经元较多时使用,减小了模型复杂度。
6.2 .解决模型欠拟合:
1.对于离散自变量,可以增添更多参数。例如在预测物品种类时,增加物品更多的属性。
2.对于连续性自变量,可以考虑增加多项式的次数。
3.取消正则化因子。
6.3.其他训练方法:
交叉验证:先将数据集划分为个大小相似的互斥子集,,每次选取个子集的并集作为训练集,剩下的为测试集,可以进行次测试,返回的是次预测结果的平均值。
7.卷积神经网络相较于MLP的优点:
在进行图像处理时,假设一幅RGB图像的长与宽皆为,那么图像矩阵中有组数据,在进行神经网络训练时输入向量维数过大。使用CNN(卷积神经网络)可以提取图像中的有效信息,将卷积后的矩阵作为输入向量,训练复杂度更小。同时,可以通过反馈机制一步步优化filter矩阵。
编程题代码:
1.图片处理:
from PIL import Image
import numpy as np
def photo_array():
I = Image.open('D:/engineer/opencv/number.jpg')
I.show()
I_array = np.array(I)
width=np.size(I_array,0)
height=np.size(I_array,1)
I_array=I_array.reshape(height,width,3)
print(I_array)
return I_array
#该函数输出一个 行数*列数*3 的矩阵
2.函数编辑:
import math
import numpy as np
def sigmoid(weight,x,b):
z=float(weight.dot(x)+b)
return 1/(1+math.exp(z))
def tanh(weight,x,b):
z=float(weight.dot(x)+b)
return (math.exp(2*z)-1)/(math.exp(2*z)+1)
def diff_sigmoid(weight,x,b):#导数1
diff1=weight
z=float(weight.dot(x)+b)
diff2=-math.exp(z)/(1+math.exp(z))**2
return diff2*diff1
def diff_tanh(weight,x,b):#导数2
diff1=weight
z=float(weight.dot(x)+b)
diff2=4/(math.exp(z)+math.exp(-z))**2
return diff2*diff1
3.使用普通的卷积运算函数
#输入:原始矩阵,filter矩阵,卷积中心点,filter矩阵长与宽
import numpy as np
import math as mt
def filter_read(mat1,mat2,r1,c1,r2,c2):
number=0
for i1 in range(r2):
for j1 in range(c2):
number+=np.dot(mat1[r1-int((r2-1)/2)+i1][c1-int((c2-1)/2)+j1],mat2[i1][j1])
return number#计算filter矩阵的每一通道与原矩阵通道的乘积
4.使用polling(寻找最大值)的方式卷积函数:
import numpy as np
import math as mt
def filter_read(mat,r1,c1,r2,c2):
mat1=np.zeros([r2,c2])
for i1 in range(r1):
for i2 in range(c1):
mat1[i1][i2]=mat[r1-(r2-1)/2+i1][c1-(c2-1)/2+i2]
return mat1
5.卷积计算函数
#函数参数为,原矩阵,步长,padding长度,filter矩阵个数,filter矩阵
def cnn(origin_mat,s,p,nf,filter_cnn):
o_row=np.size(origin_mat,0)#行数
o_col=np.size(origin_mat,1)#列数
f_row=np.size(filter_cnn[0],0)#filter行数
f_col=np.size(filter_cnn[0],1)#filter列数
origin1_mat=np.zeros([o_row+2*p,o_col+2*p,3])##三通道矩阵
for h1 in range(o_row):
for h2 in range(o_col):
origin1_mat[h1+p][h2+p]=origin_mat[h1][h2]
o_row=o_row+2*p#padding后的矩阵行
o_col=o_col+2*p#padding后的列
c_row=mt.floor((o_row+2*p-f_row)/s+1)
c_col=mt.floor((o_col+2*p-f_row)/s+1)
change_mat=np.zeros([nf,c_row,c_col])#卷积后矩阵
start_row=int((f_row-1)/2)
start_col=int((f_col-1)/2)#选取卷积中心
for i in range(nf):
for j1 in range(c_row-1):
for j2 in range(c_col-1):
print(origin1_mat[start_row][start_col])
change_mat[i][j1][j2]=filter_read(origin1_mat,filter_cnn[i],start_row,start_col,f_row,f_col)
start_col+=s
start_col=int((f_col-1)/2)
start_row+=s#卷积中心改变,使用步长
start_row=int((f_row-1)/2)
start_col=int((f_col-1)/2)
print(start_row)
return change_mat
#实际运用
test1=np.random.randint(0,255,size=[500,500,3])
#随机生成一个图片矩阵
test_s=5
test_p=2
test_nf=3
filter_cnn=np.random.randint(0,3,size=[test_nf,3,3,3])
print(filter_cnn)
new1=cnn(test1,test_s,test_p,test_nf,filter_cnn)
print(new1)
print('新矩阵的行数:',np.size(new1,0))
print('新矩阵的列数:',np.size(new1,1))
print(
结果:
读取图片卷积结果: