手写数字识别 Digit Recognizer
在这次Machine Learning中,我做一个比较经典的手写数字识别的一个项目,巩固一下自己所学的知识,也带领大家进入神经网络的时代,神经网络可以在这个分类任务上大展身手,万物皆可卷积。
如果想了解更多的知识,可以去我的机器学习之路 The Road To Machine Learning通道
OverView 项目概述
首先我们就来看看这个识别任务的简单介绍吧
MNIST (“Modified National Institute of Standards and Technology”) is the de facto “hello world” dataset of computer vision. Since its release in 1999, this classic dataset of handwritten images has served as the basis for benchmarking classification algorithms. As new machine learning techniques emerge, MNIST remains a reliable resource for researchers and learners alike.
In this competition, your goal is to correctly identify digits from a dataset of tens of thousands of handwritten images. We’ve curated a set of tutorial-style kernels which cover everything from regression to neural networks. We encourage you to experiment with different algorithms to learn first-hand what works well and how techniques compare.
MNIST (Modified National Institute of Standards and Technology)实际上是计算机视觉的“hello world”数据集。自从1999年发布以来,这个经典的手写图像数据集一直是分类算法的基准。随着新的机器学习技术的出现,MNIST仍然是研究人员和学习者的可靠资源。
在这场比赛中,您的目标是从数万张手写图像的数据集中正确识别数字。我们策划了一套教程风格的内核,涵盖了从回归到神经网络的所有内容。我们鼓励您使用不同的算法进行实验,以第一手了解哪些算法更有效以及如何比较技术。
Data Description 数据描述
MNIST 包括6万张28x28的训练样本,1万张测试样本,很多教程都会对它”下手”几乎成为一个 “典范”,可以说它就是计算机视觉里面的Hello World。所以我们这里也会使用MNIST来进行实战。
在卷积神经网络中,首先出现了一个很强大的LeNet-5,LeNet-5之所以强大就是因为在当时的环境下将MNIST数据的识别率提高到了99%,这里我们也自己从头搭建一个卷积神经网络,也达到99%的准确率
1. Introduction 项目介绍
This Notebook follows three main parts:
The data preparation
The CNN modeling and evaluation
The results prediction and submission
305 / 5000
这是一个 5 层顺序卷积神经网络,用于在 MNIST 数据集上训练的数字识别。 我选择使用非常直观的 keras API(Tensorflow 后端)来构建它。 首先,我将准备数据(手写数字图像),然后我将专注于 CNN 建模和评估。
我在单个 GPU (i7 1050Ti) 上用 训练的 CNN 达到了 99.4%的准确率。 对于那些拥有多核 GPU 能力的人,您可以将 tensorflow-gpu 与 keras 结合使用。 计算速度会快很多!!!
import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from keras.utils.np_utils import to_categorical # convert to one-hot-encoding from sklearn.model_selection import train_test_split from keras.models import Sequential from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPool2D from keras.optimizers import RMSprop %matplotlib inline
2. Data preparation 数据预处理
2.1 Load data 加载数据
# Load the data train = pd.read_csv('data/train.csv') test = pd.read_csv('data/test.csv')
我们可以查看一下数据的分布和类型等
train.info()
我们可以看到,数据中有标签label和784(28*28)个pixel,也就是我们的像素值
Y_train = train['label'] X_train = train.drop('label',axis=1) sns.countplot(y_train) y_train.value_counts()
1 4684
7 4401
3 4351
9 4188
2 4177
6 4137
0 4132
4 4072
8 4063
5 3795
Name: label, dtype: int64
We have similar counts for the 10 digits.
我们差不多有十个标签,数目差不多,就是0-9,我们的数字标签
2.2 Check for null and missing values 缺失值处理
# Check the data X_train.isnull().any().describe()
count 784
unique 1
top False
freq 784
dtype: object
test.isnull().any().describe()
count 784
unique 1
top False
freq 784
dtype: object
There is no missing values in the train and test dataset. So we can safely go ahead
训练和测试数据集中没有缺失值。 所以我们可以放心地继续前进
2.3 Normalization 标准化处理
我们实现灰度归一化以减少光照差异的影响,也就是标准化。
此外,CNN 在 [0…1] 数据上的收敛速度比在 [0…255] 上更快
# Normalize the data X_train = X_train / 255.0 test = test / 255.0
2.4 Reshape 重塑
# Reshape image in 3 dimensions (height = 28px, width = 28px , canal = 1) # 也就是将 784 像素的向量重塑为 28x28x3 的 3D 矩阵。 X_train = X_train.values.reshape(-1,28,28,1) test = test.values.reshape(-1,28,28,1)
训练和测试图像 (28px x 28px) 已作为 784 个值的一维向量存入 pandas.Dataframe。 我们将所有数据重塑为 28x28x1 3D 矩阵。
Keras 最后需要一个与通道相对应的额外维度。 MNIST 图像是灰度化的,所以它只使用一个通道。 对于 RGB 图像,有 3 个通道,我们会将 784 像素的向量重塑为 28x28x3 的 3D 矩阵。
2.5 Label encoding 标签编码
我们利用我们one-hot编码的原理来对我们的标签进行编码
# Encode labels to one hot vectors (ex : 2 -> [0,0,1,0,0,0,0,0,0,0]) y_train = to_categorical(y_train, num_classes = 10)
Labels are 10 digits numbers from 0 to 9. We need to encode these lables to one hot vectors (ex : 2 -> [0,0,1,0,0,0,0,0,0,0]).
标签是从 0 到 9 的 10 位数字。我们需要将标签编码为一个one-hot 向量(例如:2 -> [0,0,1,0,0,0,0,0,0,0])
2.6 Split training and valdiation set 拆分训练和验证集
设置随机种子
# Set the random seed random_seed = 2
拆分为训练集和验证集进行一个训练
# Split the train and the validation set for the fitting X_train, X_val, Y_train, Y_val = train_test_split(X_train, y_train, test_size = 0.1, random_state=random_seed)
I choosed to split the train set in two parts : a small fraction (10%) became the validation set which the model is evaluated and the rest (90%) is used to train the model.
Since we have 42 000 training images of balanced labels (see 2.1 Load data), a random split of the train set doesn’t cause some labels to be over represented in the validation set. Be carefull with some unbalanced dataset a simple random split could cause inaccurate evaluation during the validation.
我选择将训练集分成两部分:一小部分 (10%) 成为评估模型的验证集,其余 (90%) 用于训练模型。
由于我们有 42 000 张平衡标签的训练图像(参见 2.1 加载数据),训练集的随机拆分不会导致某些标签在验证集中过度表示。 小心一些不平衡的数据集,简单的随机拆分可能会导致验证过程中的评估不准确。
We can get a better sense for one of these examples by visualising the image and looking at the label.
我们可以可视化一下我们的图片
plt.imshow(X_train[0][:,:,0])