2018-10-30

开放实验作业

1.sigmoid函数与tanh函数的梯度消失:

写出函数表达式:
sigmoid函数:
tanh函数:
对两函数进行求导可以得到:


以sigmoid函数导数的图像为例:

sigmoid.jpg

令,当z的取值较大时,会发现两个函数的导数都会趋于0,这使得神经网络反馈进行梯度下降时十分缓慢,不利于权重的更新。举个一元多层神经网络的例子:

yiyuan.png

根据链式法则得到求导公式:

可见最终算出的权重会很小
解决办法:
1.使用ReLU函数: ReLU函数的表达式为:
,
,这样,当x大于0时,y关于x的导数恒为1,不会出现梯度消失的问题。

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(

结果:


结果.png

读取图片卷积结果:


结果2.png

你可能感兴趣的:(2018-10-30)