EX3:神经网络手写数字识别(多类分类)

EX3:神经网络手写数字识别(多类分类)

之前实现了多类逻辑回归来识别手写数字。 然而,逻辑回归不能形成更复杂的假设,因为它只是一个线性分类器。 (虽然可以向其中添加多项式特征,但训练成本可能非常高。)在这部分练习中,将使用与之前相同的训练集实现一个神经网络来识别手写数字。 神经网络将能够表示形成非线性假设的复杂模型。

目标是实现前馈传播算法。

1.数据读取

import numpy as np
from scipy.io import loadmat
data=loadmat('ex3data1.mat')
weights=loadmat('ex3weights.mat')

这里用到的data和ex3逻辑回归练习中是一样的,weights是已经训练好的神经网络权重,我们看一下它长什么样子

print一下可以看到weights中包含‘Theta1’和‘Theta2’两个部分,可以知道本次练习中我们用到的神经网络应当有两层hidden layer。

分别看看这两个权重的维度:

print(weights['Theta1'].shape,weights['Theta2'].shape)#((25,401),(10,26))

根据读取到的权重维度,可以直到网络一共有两层,其中Layer1包含25个neuron,Layer2包含10个neuron,这10个neuron的输出就是神经网络预测的结果。

注意:Layer1的输出在进入Layer2的运算前添加了偏置项。所以Layer2的系数矩阵维度发生变化,为(10,26)。

练习中神经网络架构示意图:
在这里插入图片描述

2.实现神经网络前馈传播计算

现在为神经网络实现前馈传播,实现为每个示例计算并返回相关预测的前馈计算。与一对多分类策略类似,神经网络的预测将是输出最大的标签。

注意到系数矩阵Theta1包含401列,即我们输入的X需要包含偏置列。

首先构造一下要用到的Xy

#构造X,y
X=data['X']
y=data['y']

(X.shape,y.shape)#((5000, 400), (5000, 1))

我们总共有5000个样本,包含400个特征,还包含对应的label,下面我们为X添加偏置列:

ones_col=np.ones(X.shape[0])
X=np.c_[ones_col,X]
X.shape#(5000, 401)

X和y都构造完毕,接下来我们实现神经网络前馈传播算法,该函数将返回神经网络的预测结果。

首先构造激活函数——Sigmoid函数,便于在前馈传播计算中使用。

def sigmoid(z):
    return 1/(1+np.exp(-z))

构造函数前,我们首先分析一下数据在该神经网络中的计算过程:
首先是输入数据X,X与Theta1相乘后经过激活函数生成下一层神经网络的输入:
X : ( 5000 , 401 ) T h e t a 1 : ( 25 , 401 ) z 1 = T h e t a 1. d o t ( X T ) a 1 = g ( z 1 ) : ( 25 , 5000 ) X:(5000,401) \\Theta1:(25,401) \\z1=Theta1.dot(X^T) \\a1=g(z1):(25,5000) X:(5000,401)Theta1:(25,401)z1=Theta1.dot(XT)a1=g(z1):(25,5000)
第一层的计算结果要先添加一行偏置项(全1)再进入下一层的计算,与Theta2相乘以后经过激活函数得到输出:
a 1 : ( 25 , 5000 ) T h e t a 2 : ( 10 , 26 ) a 1 添 加 行 : ( 26 , 5000 ) z 2 = T h e t a 2. d o t ( a 1 ) a 2 = g ( z 2 ) : ( 10 , 5000 ) a1:(25,5000) \\Theta2:(10,26) \\a1添加行:(26,5000) \\z2=Theta2.dot(a1) \\a2=g(z2):(10,5000) a1:(25,5000)Theta2:(10,26)a1:(26,5000)z2=Theta2.dot(a1)a2=g(z2):(10,5000)
每一列都是针对某一个样本的输出结果.

最后我们要输出该神经网络的预测结果,用到numpy库中一个函数argmax,函数说明如下

numpy.argmax(a,axis=0/1)
对二维矩阵a:
若axis=0则沿列方向搜索每一列最大的数并返回其列索引;
若axis=1则沿行方向搜索每一列最大的数并返回其行索引

注意我们的索引范围应当在0-9,而预测的数字为1-10,所以我们要将argmax返回的结果+1再输出。

def predict(Theta1,Theta2,X):
    #layer1
    a1=sigmoid(Theta1.dot(X.T))
    #add bias
    ones_col=np.ones((1,a1.shape[1]))
    a1=np.r_[ones_col,a1]
    #layer2
    a2=sigmoid(Theta2.dot(a1))

    pre_max=np.argmax(a2,axis=0)#搜索每一列最大值并返回列索引
    return pre_max+1

函数构造完毕,我们来输出一下网络预测的准确性:

result=predict(weights['Theta1'],weights['Theta2'],X)
correct=np.array([1 if result[i]==y[i] else 0 for i in range(len(y))])

print("Accuracy:{}%".format(correct.sum()/len(correct)*100))#Accuracy:97.52%

根据练习说明文档中写的“我们将得到accuracy大概97.5%”可知算法正确运行。

  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数字识别在Matlab中是一个非常常见的问题,可以使用机器学习算法来解决。下面是一个简单的数字识别的Matlab代码示例: 1. 加载数据集 ```matlab load('ex3data1.mat'); ``` 2. 显示数据集中的图像 ```matlab m = size(X, 1); rand_indices = randperm(m); sel = X(rand_indices(1:100), :); displayData(sel); ``` 3. 定义神经网络模型 ```matlab input_layer_size = 400; % 20x20 输入图像 hidden_layer_size = 25; % 隐藏层25个单元 num_labels = 10; % 10 个输出标签,即数字 0 到 9 % 随机初始化权重参数 initial_Theta1 = randInitializeWeights(input_layer_size, hidden_layer_size); initial_Theta2 = randInitializeWeights(hidden_layer_size, num_labels); % 将权重参数展开成一维向量 initial_nn_params = [initial_Theta1(:) ; initial_Theta2(:)]; ``` 4. 定义代价函数和梯度函数 ```matlab % 代价函数 [J, grad] = nnCostFunction(nn_params, input_layer_size, hidden_layer_size, num_labels, X, y, lambda); % 梯度函数 function [J grad] = nnCostFunction(nn_params, input_layer_size, hidden_layer_size, num_labels, X, y, lambda) Theta1 = reshape(nn_params(1:hidden_layer_size * (input_layer_size + 1)), hidden_layer_size, (input_layer_size + 1)); Theta2 = reshape(nn_params((1 + (hidden_layer_size * (input_layer_size + 1))):end), num_labels, (hidden_layer_size + 1)); m = size(X, 1); J = 0; Theta1_grad = zeros(size(Theta1)); Theta2_grad = zeros(size(Theta2)); X = [ones(m, 1) X]; z2 = X * Theta1'; a2 = sigmoid(z2); a2 = [ones(m, 1) a2]; z3 = a2 * Theta2'; h = sigmoid(z3); yk = zeros(m, num_labels); for i=1:m yk(i,y(i)) = 1; end J = (-1/m) * sum(sum(yk.*log(h) + (1-yk).*log(1-h))) + (lambda/(2*m)) * (sum(sum(Theta1(:,2:end).^2)) + sum(sum(Theta2(:,2:end).^2))); delta3 = h - yk; delta2 = delta3 * Theta2 .* sigmoidGradient([ones(m, 1) z2]); delta2 = delta2(:, 2:end); Delta1 = delta2' * X; Delta2 = delta3' * a2; Theta1_grad = (1/m) * Delta1 + (lambda/m) * [zeros(size(Theta1, 1), 1) Theta1(:, 2:end)]; Theta2_grad = (1/m) * Delta2 + (lambda/m) * [zeros(size(Theta2, 1), 1) Theta2(:, 2:end)]; grad = [Theta1_grad(:) ; Theta2_grad(:)]; end ``` 5. 训练模型 ```matlab options = optimset('MaxIter', 50); lambda = 1; costFunction = @(p) nnCostFunction(p, input_layer_size, hidden_layer_size, num_labels, X, y, lambda); [nn_params, cost] = fmincg(costFunction, initial_nn_params, options); Theta1 = reshape(nn_params(1:hidden_layer_size * (input_layer_size + 1)), hidden_layer_size, (input_layer_size + 1)); Theta2 = reshape(nn_params((1 + (hidden_layer_size * (input_layer_size + 1))):end), num_labels, (hidden_layer_size + 1)); ``` 6. 测试模型 ```matlab pred = predict(Theta1, Theta2, X); fprintf('\nTraining Set Accuracy: %f\n', mean(double(pred == y)) * 100); ``` 7. 预测新的数字图像 ```matlab % 加载新的数字图像 img = imread('new_digit.png'); % 转换成灰度图像 img = rgb2gray(img); % 转换成二值图像 img = im2bw(img, 0.5); % 调整图像大小 img = imresize(img, [20 20]); % 将图像转换成向量 X_new = img(:)'; % 预测数字 pred_new = predict(Theta1, Theta2, X_new); fprintf('\nPredicted Number: %d\n', mod(pred_new, 10)); ``` 以上是一个简单的数字识别的Matlab代码示例,其中包括数据加载、神经网络模型定义、代价函数和梯度函数、模型训练、模型测试和预测新的数字图像等步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值