吴恩达|机器学习作业3.1前馈神经网络

3.1.前馈神经网络

1)题目:

在本次练习中,你将使用前馈神经网络来识别手写数字(从0到9)。数据依然是MNIST手写体数据集,这里包含了5000个训练样本。之前用了逻辑回归进行多元分类,这次用前馈神经网络进行预测。
此外作业中已经给出了训练好的权重,这部分数据可以在下次作业中自己训练出来,现在先用训练好的权重直接得出前馈神经网络的结果。
数据集链接: https://pan.baidu.com/s/1cEgQIvehUcLxZ0WVhxcPuQ 提取码: xejn

2)知识点概括:

  • 在解决非线性假设问题中,当特征很多时如果还是利用logistic回归,那多项式的特征数目将会以初始特征数目的指数级速度产生,这样会造成算法运算量过大,甚至过拟合。神经网络在解决非线性假设问题特征数很大的情况下一种非常好的算法。在数学上已经证明,只需一个包含足够多神经元的隐层,多层前馈网络就可以以任意精度逼近任意复杂度的连续函数。因此可以看书神经网络之强大。
  • 类似于神经元细胞体,通过类似于树突的输入通道传递给神经元信息让它工作,再通过类似于轴突的输出通道输出结果。h在这里称为激活函数(activation function),我们称这个逻辑单元(logistic unit)是一个带激活函数的人工神经元(artificial neuron)。在激活函数中的参数又叫模型的权重。
  • 此外有时还可以设置一个值为1的偏置单元(bias unit)。
  • 第一层叫输入层(input layer),在这一层输入特征;最后一层叫输出层(output layer)输出最后的结果;中间层叫隐层(hidden layer)看不到输入或者输出的值。
  • 在我的理解中,前馈神经网络通俗的说就是样本和第一层权重的线性组合,再复合激活函数,用这个值再与第二层权重线性组合,再复合激活函数,然后再用这个值与第三层权重线性组合…直到最后一层复合完激活函数之后的值就是前馈神经网络的预测值。其本质就是激活函数的多层复合。

在这里插入图片描述

3)大致步骤:

首先依然是用scio.loadmat读取mat数据,分别将训练样例和训练集标签设置为x和y,已经训练好的权重分别标记为theta1和theta2。上一篇作业已经进行了数据的可视化,因此本次作业直接进行训练(其实也不是训练,因为这里参数已经被训练好了,只需计算向前传播的公式即可)。
首先选择网络框架,这里作业中给出了框架,即包含输入层、隐层和输出层的3层框架。由于x的维度是5000乘400,即有400个特征,因此输入层的神经元数量为400(不包含偏置单元,即常数项1),隐层的神经元数量作业中给出为25(不包含偏置单元),输出层的神经元数量由分类的类数所决定,因此是10。
在这里插入图片描述
然后再逐层地向前传播,直到输出层得到预测值,再用预测值与期望值进行比较计算出精度,预测精度应该在97.5%左右。这里列出来写前馈函数时大概流程,主要是对矩阵的维数进行检查以免错误。(两个大括号分别对应代码里前馈函数的两次循环)
在这里插入图片描述

4)关于Python:

  • locals( )[‘theta’+str(i)]可以调用theta i 的值,用在for循环中。
  • for循环里面的语句好像有点并行处理的意思,因为在定义前馈函数的时候,刚开始没有添加的变量,只用了,导致出现矩阵乘法维数对不上的而报错的情况,但是实际从逻辑角度看这样写是没有问题的,手动一行行执行代码也能正常运行,猜想可能是因为在for循环第一行调用了一个在矩阵前补一列的函数,第二行执行时第一行还没执行完,仍然使用的是补之前的矩阵,所以才报错。因此,在以后在变量命名时要注意,尽量不要混淆!
    下面是改之前的代码以及报错信息:
#前馈函数
def forward_pro(x, theta1, theta2): #如果多层可添加theta
    a1 = x  #(5000, 400)
    for i in range(1,3): #如果为n层网络,则这里的3改为n即可
        locals()['a'+str(i)] = plus1(locals()['a'+str(i)])
        locals()['z'+str(i+1)] = locals()['a'+str(i)]@locals()['theta'+str(i)].T
        locals()['a'+str(i+1)] = g(locals()['z'+str(i+1)])
        if i+1 == 3:  #如果为n层网络,则这里的3改为n即可
            a3 = g(locals()['z'+str(i+1)])
    return a3  #(5000, 10)  如果为n层网络,这样输出也是an

在这里插入图片描述

5)代码与结果:


import numpy as np
import matplotlib.pyplot as plt
import scipy.io as scio #读取mat文件
import scipy.optimize as opt

data = scio.loadmat('ex3data1.mat')
weights = scio.loadmat('ex3weights.mat')
x = data['X']
y = data['y']
theta1 = weights['Theta1']
theta2 = weights['Theta2']

'''向前传播'''
#sigmoid函数作为激活函数
def g(x):
    return 1/(1+np.exp(-x))

#前面加一列1的函数
def plus1(x):
    return np.column_stack((np.ones(x.shape[0]), x))


#前馈函数
def forward_pro(x, theta1, theta2): #如果多层可添加theta
    b1 = x  #(5000, 400)
    for i in range(1,3): #如果为n层网络,则这里的3改为n即可
        locals()['a'+str(i)] = plus1(locals()['b'+str(i)])
        locals()['z'+str(i+1)] = locals()['a'+str(i)]@locals()['theta'+str(i)].T
        locals()['b'+str(i+1)] = g(locals()['z'+str(i+1)])
        if i+1 == 3:  #如果为n层网络,则这里的3改为n即可
            b3 = g(locals()['z'+str(i+1)])
    return b3  #(5000, 10)  如果为n层网络,这样输出也是an


'''预测与评价'''
#预测的y值
def predict(prob):
    y_predict = np.zeros((prob.shape[0],1))
    for i in range(prob.shape[0]):
        #查找第i行的最大值并返回它所在的位置,再加1就是对应的类别
        y_predict[i] = np.unravel_index(np.argmax(prob[i,:]), prob[i,:].shape)[0]+1
    return y_predict
        
#精度
def accuracy(y_predict, y=y):
    m = y.size
    count = 0
    for i in range(y.shape[0]):
        if y_predict[i] == y[i]:
            j = 1 
        else:
            j = 0
        count = j+count #计数预测值和期望值相等的项
    return count/m
    
#预测的概率矩阵 (5000, 10)        
prob = forward_pro(x, theta1, theta2)
y_predict = predict(prob)
accuracy(y_predict)
print ('accuracy = {0}%'.format(accuracy(y_predict) * 100))

最后的预测精度:
在这里插入图片描述

发布了32 篇原创文章 · 获赞 33 · 访问量 6639

猜你喜欢

转载自blog.csdn.net/weixin_44750583/article/details/88616730
今日推荐