环境:python,anaconda ,tensorflow
数据来源:kaggle网站:https://www.kaggle.com/c/digit-recognizer/data
import numpy as np
import pandas as pd
#获取数据
train_data = pd.read_csv('./dataset/digit-recognizer/train.csv')
test_data = pd.read_csv('./dataset/digit-recognizer/test.csv')
#查看数据样式
train_data.head()
#查看数据中有没有缺失值
##(看样子没有缺失值)
Col_with_missing = [col for col in train_data.columns if train_data[col].isnull().any()]
print(Col_with_missing)
#输出:[]
Col_with_missing = [col for col in test_data.columns if test_data[col].isnull().any()]
print(Col_with_missing)
#输出:[]
#查看训练数据中各个类别的分布情况
Y_train.value_counts()
#输出如下:(看上去还算均匀,如果各类别数据明显不均衡会影响训练结果)
#1 4684
#7 4401
#3 4351
#9 4188
#2 4177
#6 4137
#0 4132
#4 4072
#8 4063
#5 3795
#再用如下柱状图看一下个数据分布情况
import seaborn as sns
%matplotlib inline
sns.countplot(Y_train)
#我们数据集中的图像是28*28
img_row = 28
img_col = 28
#对图像数据归一化方法
def data_prep_X(X):
num_img=len(X)
x_as_array = X.values.reshape(num_img,img_row,img_col,1)
X_out = x_as_array / 255
return X_out
from keras.utils.np_utils import to_categorical
num_classes = 10
#将标签数据转为one_hot格式
def data_prep_Y(Y):
out_y = to_categorical(Y,num_classes)
return out_y
#对数据进行归一化处理
X_train = data_prep_X(X_train)
test_data = data_prep_X(test_data)
#标签数据转为one-hot
Y_train = data_prep_Y(Y_train)
#看看归一化后的图像样式
import matplotlib.pyplot as plt
plt.imshow(X_train[0][:,:,0])
from tensorflow.python import keras
from tensorflow.python.keras.models import Sequential
from tensorflow.python.keras.layers import Dense,Flatten,Conv2D
from tensorflow.keras.callbacks import EarlyStopping
#EarlyStopping早停法,防止过拟合,此处我们不用
#early_stop = EarlyStopping(monitor='val_loss',patience=1)
#如下模型有3层卷积层
#Flatten,卷积层之后是无法直接连接Dense全连接层的,
#需要把卷积层的数据压平(Flatten),然后就可以直接加Dense层了
#Conv2D(20,kernel_size=(3,3)
# 20表示卷积核的个数,也可以自己设定,但是要考虑计算速度和防止过拟合
# (3,3)表示卷积核大小,也可以自己设定
#模型的结构可以自己设定,比如加入池化以及droupout等,模型的变化会对计算速度和准确度有影响
model = Sequential()
model.add(Conv2D(20,kernel_size=(3,3),
activation='relu',
input_shape=(img_row,img_col,1)))
model.add(Conv2D(20,kernel_size=(3,3),
activation='relu'))
model.add(Flatten())
model.add(Dense(128,activation='relu'))
model.add(Dense(num_classes,activation='softmax'))
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer='adam',
metrics=['accuracy'])
#开始训练validation_split 表示将数据分割为训练数据和验证数据的比例
model.fit(X_train,Y_train,
batch_size=128,
epochs=20,
validation_split=0.2,
#callbacks=[early_stop]
)
#训练过程中的损失和准确度
losses_acc = pd.DataFrame(model.history.history)
losses_acc
#损失图像如下
losses_acc[['loss','val_loss']].plot()
# 预测
results = model.predict(test_data)
results = np.argmax(results,axis = 1)
results = pd.Series(results,name="Label")
print(results)
#如下可以看到预测结果第一个图像预测为2,第二个预测为0,第三那个预测为9
#我们画图看一下预测预测结果为2的第一个图像是什么样子
plt.imshow(test_data[0][:,:,0])
#第27998个图像(预测为9)
plt.imshow(test_data[27998][:,:,0])
#我们将预测结果保存为mySubmission.csv
submission = pd.concat([pd.Series(range(1,28001),name = "ImageId"),results],axis = 1)
submission.to_csv("mySubmission.csv",index=False)
至此我们一个简单的通过CNN训练的手写体数字识别就完成了!
首次发帖不喜勿喷,欢迎指正