你好,我是小航,一个正在变秃、变强的文艺倾年。
本文讲解卷积神经网络:打破图像识别的瓶颈,一起卷起来叭!
目录
- 一、手写体识别
- 二、“炼丹”
在机器学习、神经网络领域,有一个应用层的经典“Hello World”:手写体识别
,于是它成为了众多入门者的实践项目。
这是一个手写体“5”
,它是由 28 * 28 的灰度图,每一个像素用一个字节的无符号数表示它的等级。如果是0,那就是最暗(纯黑色);如果是255,那就是最亮(纯白色)。
现实中,人毕竟不同于精准但呆板的计算机,每次手写一个数字都可能不太一样,比如第一次我们写成这样:
第二次由于手抖写成这样:
这时候就没有什么确定的规则
去根据像素的灰度值判断是什么数字了,换句话说这不再是一个适用于计算机机械逻辑做判断
的问题,我们需要用有一定的容错能力的系统来做这件事,很明显神经网络
是一个很好的选择。
我们把mnist数据集(手写图片数据)以784维向量作为输入,依次送入神经网络进行训练就好。
模型在训练集和测试集上的不同表现导致了机器学习中三种常见的现象:
1.训练集准确率很低,额,这个模型多半是废了,这个现象称为欠拟合
,可能模型过于简单
2.训练集准确率高,测试集准确率低,说明该模型拥有很好的泛化能力
,有能力去解决新的问题
3.训练集和测试集准确率都很高,说明这个模型的泛化能力不行,称为过拟合
,原因有很多,比如用一个过分复杂的模型拟合一个实则简单的问题,,当然解决过拟合也有很多方式,比如:调整神经网络结构、L2正则化、节点失活(Dropout)正则化等等
当然这节我们主要以全连接神经网络讲解,而图像作为一个二维物体,相邻元素之间总是存在关联的,如果我们强行把它降低到一维也就破坏了这些关联,失去了重要的特征。在实际中,卷积神经网络会有更好的效果,也是更为常用的方法。这也说明了重要特征对提高模型的泛化能力有很大作用
。
至于如何提取重要特征,这里简单说明一下,我们还是以上面的“5”
为例:
嗯…怎么快速理解这个卷积核呢,我们以一幅茶杯图像为例,思考卷积后的图像是什么样子呢?
结果发现,把垂直的边沿给提取出来了。
你会发现,结果图片都有垂直条纹的特征
我们在搞一张极端的情况,还是以上面的杯子为例:
我们对这个图像进行卷积,机智如你,会发现:只有中间两列有值,其他两列均为0
对于两边,它们就会在左右的一正一负相互抵消
对于中间部分,左大右小完全不对称,加起来之后就会把这个值变得很大,或者说特征被凸显出来了
我们对上述过程代码实现:mnist_recognizer.py
# 导入数据集
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import SGD
import matplotlib.pyplot as plt
# one-hot编码转化
from keras.utils import to_categorical
(X_train, Y_train), (X_test, Y_test) = mnist.load_data()
# 查看样本数据的类型:60000, 28, 28
print("X_train.shape:" + str(X_train.shape))
print("X_test.shape:" + str(X_test.shape))
print("Y_train.shape:" + str(Y_train.shape))
print("Y_test.shape:" + str(Y_test.shape))
# # 打印标签值
# print(Y_train[0])
# # 训练集的第一个样本数据,绘图模式:灰度图
# plt.imshow(X_train[0], cmap="gray")
# plt.show()
# 28 * 28 = 784 二维变一维
X_train = X_train.reshape(60000, 784) / 255.0 # 减少差距,加快梯度下降
X_test = X_test.reshape(10000, 784) / 255.0
Y_train = to_categorical(Y_train, 10)
Y_test = to_categorical(Y_test, 10)
model = Sequential()
model.add(Dense(units=256, activation='relu', input_dim=784))
model.add(Dense(units=256, activation='relu'))
model.add(Dense(units=256, activation='relu'))
model.add(Dense(units=10, activation='softmax'))
# 使用多分类交叉熵代价函数
model.compile(loss='categorical_crossentropy', optimizer=SGD(lr=0.05), metrics=['accuracy'])
model.fit(X_train, Y_train, epochs=5000, batch_size=256)
loss, accuracy = model.evaluate(X_test, Y_test)
print("loss" + str(loss))
print("accuracy" + str(accuracy))
训练结果与模型测试:
[ 笔者 ] 文艺倾年
[ 更新 ] 2023.1.22
❌ [ 勘误 ] /* 暂无 */
[ 声明 ] 由于作者水平有限,本文有错误和不准确之处在所难免,
本人也很想知道这些错误,恳望读者批评指正!
[ 代码 ] https://github.com/itxaiohanglover/ai_lesson