使用keras 进行图片分类,这里采用了fashion_mnist
参考链接:https://www.kaggle.com/zalando-research/fashionmnist
关于cnn这里就不多讲了,可以参考:https://blog.csdn.net/cqy_chen/article/details/78959687
欢迎关注博客:https://blog.csdn.net/cqy_chen
ps:跑之前请下在fashion-mnist数据集,可以参考:https://blog.csdn.net/cqy_chen/article/details/80059576
#导入相关的包并读取训练数据
import pandas as pd;
import numpy as np
from subprocess import check_output
from keras.utils import to_categorical
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn import neighbors
import datetime
import numpy as np
import struct
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn.model_selection import learning_curve #加载学习曲线
from sklearn.model_selection import validation_curve #加载验证曲线
from sklearn.model_selection import ShuffleSplit #加载数据处理
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.layers.normalization import BatchNormalization
def read_image(file_name):
'''
:param file_name: 文件路径
:return: 训练或者测试数据
如下是训练的图片的二进制格式
[offset] [type] [value] [description]
0000 32 bit integer 0x00000803(2051) magic number
0004 32 bit integer 60000 number of images
0008 32 bit integer 28 number of rows
0012 32 bit integer 28 number of columns
0016 unsigned byte ?? pixel
0017 unsigned byte ?? pixel
........
xxxx unsigned byte ?? pixel
'''
file_handle=open(file_name,"rb") #以二进制打开文档
file_content=file_handle.read() #读取到缓冲区中
head = struct.unpack_from('>IIII', file_content, 0) # 取前4个整数,返回一个元组
offset = struct.calcsize('>IIII')
imgNum = head[1] #图片数
width = head[2] #宽度
height = head[3] #高度
bits = imgNum * width * height # data一共有60000*28*28个像素值
bitsString = '>' + str(bits) + 'B' # fmt格式:'>47040000B'
imgs = struct.unpack_from(bitsString, file_content, offset) # 取data数据,返回一个元组
imgs_array=np.array(imgs).reshape((imgNum,width*height)) #最后将读取的数据reshape成 【图片数,图片像素】二维数组
return imgs_array
def out_image(img):
'''
:param img: 图片像素组
:return:
'''
plt.figure()
plt.imshow(img)
plt.show()
def read_label(file_name):
'''
:param file_name:
:return:
标签的格式如下:
[offset] [type] [value] [description]
0000 32 bit integer 0x00000801(2049) magic number (MSB first)
0004 32 bit integer 60000 number of items
0008 unsigned byte ?? label
0009 unsigned byte ?? label
........
xxxx unsigned byte ?? label
The labels values are 0 to 9.
'''
file_handle = open(file_name, "rb") # 以二进制打开文档
file_content = file_handle.read() # 读取到缓冲区中
head = struct.unpack_from('>II', file_content, 0) # 取前2个整数,返回一个元组
offset = struct.calcsize('>II')
labelNum = head[1] # label数
bitsString = '>' + str(labelNum) + 'B' # fmt格式:'>47040000B'
label = struct.unpack_from(bitsString, file_content, offset) # 取data数据,返回一个元组
return np.array(label)
def get_data():
# 文件获取
train_image = "./input/train-images-idx3-ubyte"
test_image = "./input/t10k-images-idx3-ubyte"
train_label = "./input/train-labels-idx1-ubyte"
test_label = "./input/t10k-labels-idx1-ubyte"
# 读取数据
train_x = read_image(train_image)
test_x = read_image(test_image)
train_y = read_label(train_label)
test_y = read_label(test_label)
return train_x,train_y,test_x,test_y
数据集切分,分为训练集/验证集/测试集
train_X,train_y,test_X,test_y=get_data() #这里的test_y可以假装没有看到,最后进行模型测试的才会做。
train_X,validation_X,train_y,validation_y= train_test_split(train_X,train_y,test_size=0.2,random_state=0) #切割训练集 验证集
row_nums=28
col_nums=28
batch_size=512
input_shape=(row_nums,col_nums,1)
epochs=100
#这里需要重塑数据的形状,注意点在于需要对标签进行onehot编码。
train_X=train_X.reshape(train_X.shape[0],*input_shape)
validation_X=validation_X.reshape(validation_X.shape[0],*input_shape)
test_X=test_X.reshape(test_X.shape[0],*input_shape)
validation_y = keras.utils.to_categorical(validation_y, num_classes=10)
test_y = keras.utils.to_categorical(test_y, num_classes=10)
train_y = keras.utils.to_categorical(train_y, num_classes=10)
设计cnn模型
model = Sequential()
model.add(Conv2D(filters=32, kernel_size=3, activation='relu', input_shape=input_shape))
model.add(MaxPooling2D())
model.add(Dropout(0.2))
model.add(BatchNormalization())
#model.add(BatchNormalization())
model.add(Conv2D(filters=64, kernel_size=3, activation='relu', input_shape=input_shape))
model.add(MaxPooling2D())
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
history=model.fit(train_X,
train_y,
validation_data=(validation_X, validation_y),
epochs=12,
batch_size=64,
verbose=1
)
模型结果:
plt.plot()
plt.plot(history.history['val_acc'])
plt.plot(history.history['acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['validation', 'acc'], loc='upper left')
plt.show()
其实训练的不是很好的,这就是深度学习的痛点。懒得去调参了,改模型架构都很烦人的呢。
最后测试集合上结果:
model.evaluate(test_X,test_y)
[0.25593922078311443, 0.9127]
测试集合上表现为91%的准确率,还算可以啦,讲究看看吧,本文主要是入门的。