1. 数字识别分析分析
分析对象
自动手写数字识别在今天被广泛使用——从识别信封上的邮政编码(邮政编码)到识别银行支票上写的金额。在本练习中,您将使用逻辑回归和神经网络来识别手写数字(从0到9)。您将扩展之前的逻辑回归实现,并将其应用于one-vs-all分类。
数据以.mat格式储存,mat格式是matlab的数据存储格式,按照矩阵保存,与numpy数据格式兼容,适合于各种数学运算,因此主要使用numpy进行运算。
数据中有5000个训练样例,其中每个训练样例是一个20×20像素灰度图像的数字,每个像素由一个浮点数表示,该浮点数表示该位置的灰度强度。每个20×20像素的网格被展开成一个400维的向量。这些每个训练样例都变成数据矩阵X中的一行。这就得到了一个5000×400矩阵X,其中每一行都是手写数字图像的训练样例。训练集的第二部分是一个包含训练集标签的5000维向量y,“0”的数字标记为“10”,而“1”到“9”的数字按自然顺序标记为“1”到“9”。
本部分题目内容与上一节相同,只是采用神经网格进行手写数字识别,所需要的Theta参数通过加载课程文件导入。
计算程序
import numpy as np
from matplotlib import pyplot as plt
from scipy.io import loadmat
# 读取数据
def read_data(path):
data = loadmat(path)
return data
# 处理数据
def deal_data(data):
X = np.matrix(data['X'])
y = np.matrix(data['y'])
return X, y
# 处理权重
def deal_weights(data):
theta1 = np.matrix(data['Theta1'])
theta2 = np.matrix(data['Theta2'])
return theta1, theta2
# 对数据进行可视化的函数
def visualizeData(X):
# 画布上定义10*10的子图
fig, ax = plt.subplots(10, 10)
for i in range(0, 10):
for j in range(0, 10):
magicNum = np.random.randint(5000) # 在0~5000之中生成随机整数
# 注意下面需要进行reshape,从1*400重构会20*20的像素点,gray_r代表是白底黑字
ax[i][j].imshow(X[magicNum,:].reshape(20, 20), cmap='gray_r') # 进行图片绘制
# 消除坐标轴,主要为了美观
ax[i][j].set_xticks([])
ax[i][j].set_yticks([])
plt.show()
# 预测函数
def predict_all(X, all_theta):
y_pre = 0
return y_pre
# Sigmoid激活函数
def sigmoid(z):
return 1/(1 + np.exp(-z))
# 前向传播
def forwardPropagation(X, theta1, theta2):
# a1 = xi
a1 = np.c_[np.ones((X.shape[0], 1)), X]
a2 = sigmoid(theta1 @ a1.T)
a2 = np.insert(a2, 0, values=1, axis=0)
a3 = sigmoid(theta2 @ a2)
return a3
if __name__ == '__main__':
path = '.\\data\\ex3data1.mat'
path2 = '.\\data\\ex3weights.mat'
data = read_data(path)
X, y = deal_data(data)
# 数据可视化
visualizeData(X)
all_theta = read_data(path2)
# Theta1.shape = (25, 401) a1层具有400个参数,a2层具有25个参数
# Theta2.shape = (10, 26) a3层具有10个输出参数
theta1, theta2 = deal_weights(all_theta)
# 进行精度预测
a3 = forwardPropagation(X, theta1, theta2)
# 因为是多元分类,因此这里需要选择每一个样本在训练集中的最大的分类器
prediction = np.argmax(a3, axis=0) + 1
# 将真值y从2维数据缩减成1维数据
y = y.flatten()
# 输出精度
print('accuracy:', np.mean(y == prediction) * 100, '%')
运行结果
说明
- 各个参数的数据格式如下,行数和列数可以进行颠倒,只要计算时对应上就可以。
X:
y:
theta1:
theta2:
a1 :
a2:
a3:
其中,a3为输出单元,格式为(10, 5000),包含5000个预测结果,每个结果内包含对10个分类。通过找到每一列中最大数值对应的行数来判断当前预测分类,在Python其具体内容如下:
[[1.12661530e-04 4.79026796e-04 8.85702310e-05 ... 5.17641791e-02
8.30631310e-04 4.81465717e-05]
[1.74127856e-03 2.41495958e-03 3.24266731e-03 ... 3.81715020e-03
6.22003774e-04 4.58821829e-04]
[2.52696959e-03 3.44755685e-03 2.55419797e-02 ... 2.96297510e-02
3.14518512e-04 2.15146201e-05]
...
[4.01468105e-04 2.39107046e-03 6.22892325e-02 ... 2.15667361e-03
1.19366192e-02 5.73434571e-03]
[6.48072305e-03 1.97025086e-03 5.49803551e-03 ... 6.49826950e-01
9.71410499e-01 6.96288990e-01]
[9.95734012e-01 9.95696931e-01 9.28008397e-01 ... 2.42384687e-05
2.06173648e-04 8.18576980e-02]]
- 部分函数用法:
# 使用 np.argmax(a3, axis=0) + 1 获取每一列中最大值的索引,然后加1得到预测值
prediction = np.argmax(a3, axis=0) + 1
# 将真值 y 从2维数据缩减成1维数据
y = y.flatten()
# 计算预测精度,np.mean(y == prediction) 计算预测值与真实值相等的比例,乘以 100 得到百分比
accuracy = np.mean(y == prediction) * 100
# 输出精度
print('accuracy:', accuracy, '%')
accuracy = np.mean(y == prediction) * 100
这行代码使用 NumPy 的向量比较功能来计算预测的精度。具体步骤如下:
y == prediction
:这个部分会生成一个布尔型数组,其中每个元素都是对应位置上y
和prediction
相等的布尔值。如果相等,对应位置的值为True
,否则为False
。
np.mean(y == prediction)
:计算上述布尔数组中True
的比例,也就是相等的比例。这个比例即为正确预测的样本占总样本数的比例。
* 100
:将比例乘以 100,将结果转换为百分比形式。
所以,accuracy = np.mean(y == prediction) * 100
的含义是计算正确预测的样本占总样本数的百分比。