实现将mnist数据集保存为图片文件
代码如下
import struct
from PIL import Image
import os
import numpy as np
# 参考文献 https://blog.csdn.net/u013066730/article/details/53769524
# 在此基础上做了修改
def save_image(filename, labels, save_dir, max_read):
"""
读取mnist文件,以图片形式按照所属类别进行保存
:param filename: mnist文件名
:param labels: 图片对应的标签
:param save_dir: 要保存的目录
:param max_read: 最多读取多少图片
"""
# 读入文件
f = open(filename, 'rb')
index = 0
buf = f.read()
f.close()
# 读取图片总数
magic, total, rows, columns = struct.unpack_from('>IIII', buf, index)
index += struct.calcsize('>IIII')
count = min(max_read, total)
for i in range(count):
# 读取一幅图片 28*28=784字节
im = struct.unpack_from('>784B', buf, index)
index += struct.calcsize('>784B')
im = np.array(im, dtype='uint8')
im = im.reshape(28, 28)
# 调试时显示一下
# fig=plt.figure()
# plotwindow=fig.add_subplot(111)
# plt.imshow(im,cmap='gray')
# plt.show()
# 保存到文件
im = Image.fromarray(im)
save_file = os.path.join(save_dir, str(labels[i]), '{:05d}.png'.format(i))
im.save(save_file, 'png')
print('save to ', save_file)
def read_label(filename, max_read):
"""
读取标签
:param filename: 标签文件名
:param max_read: 最多读取数量
:return: 读取的标签列表
"""
# 打开文件并读入
f = open(filename, 'rb')
index = 0
buf = f.read()
f.close()
# 读取总数量
magic, total = struct.unpack_from('>II', buf, index)
index += struct.calcsize('>II')
count = min(max_read, total)
labelArr = [0] * count
# 依次读入标签,每个标签占一个字节
for x in range(count):
labelArr[x] = int(struct.unpack_from('>B', buf, index)[0])
index += struct.calcsize('>B')
return labelArr
def save_label(labels, save_dir):
"""
保存标签
:param labels: 标签列表
:param save_dir: 保存目录
:return: None
"""
save = open(os.path.join(save_dir, 'label.txt'), 'w')
save.write(','.join(map(lambda x: str(x), labels)))
save.write('\n')
save.close()
print('save labels success')
def create_10_dir(parent):
"""
创建0-9这10个目录(若已存在则不创建)
:param parent:
:return:
"""
for i in range(10):
dir = os.path.join(parent,str(i))
if not os.path.isdir(dir):
os.mkdir(dir)
if __name__ == '__main__':
save_dir = 'e:\\smartcar\\tf\\train'
create_10_dir(save_dir)
max_read = 10000
labels = read_label('E:\\smartcar\\t10k/train-labels.idx1-ubyte', max_read)
save_label(labels, save_dir)
save_image('E:\\smartcar\\t10k/train-images.idx3-ubyte', labels, save_dir, max_read)
save_dir ='e:\\smartcar\\tf\\test'
create_10_dir(save_dir)
create_10_dir(savet_dir+'2')
max_read = 100
labels = read_label('E:\\smartcar\\t10k/t10k-labels.idx1-ubyte', max_read)
save_label(labels, save_dir)
save_image('E:\\smartcar\\t10k/t10k-images.idx3-ubyte', labels, save_dir, max_read)
可能出现的问题:
1.找不到文件,原因是没有下载相应文件
解决办法:
进入http://yann.lecun.com/exdb/mnist/把出现的四个文件下载,使用时一定要添加到相应路径,如我下载到E:\smartcar\t10k下,使用时一定加上前缀。
2.路径无效,Windows系统下的文件路径是使用“\",Linux下使用”/“,但是这里不能使用E:\smartcar\t10k\train-labels.idx1-ubyte,如果这样使用会导致数据集无法保存到正确路径。
解决办法:
一定使用"/",可这样使用:E:\smartcar\t10k/train-labels.idx1-ubyte,也可以这样使用E:/smartcar/t10k/train-labels.idx1-ubyte
运行正确后如图:
对指定目录下的图片实现分类训练
要注意,在放置图片时,图片所在的目录就是其所属类别
代码如下:
import sys
import os
from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers
from keras.models import Sequential
from keras.layers import Dropout, Flatten, Dense, Activation
from keras.layers.convolutional import Convolution2D, MaxPooling2D
from keras import callbacks
import time
# 本文件训练分类模型
# 记录训练开始时间
start = time.time()
# 开发调试标志
DEV = True
if DEV:
epochs = 10
else:
epochs = 20
# 要训练的图片所在目录
train_data_path = 'e:\\smartcar\\tf\\train'
# 验证图片所在目录
validation_data_path = 'e:\\smartcar\\tf\\test'
"""
参数
"""
img_width, img_height = 150, 150
batch_size = 32
samples_per_epoch = 1000
validation_steps = 300
# 输出数量
nb_filters1 = 32
nb_filters2 = 64
# 卷积核大小
conv1_size = 3
conv2_size = 2
# 下采样
pool_size = 2
# 分类数
classes_num = 10
# 学习率
lr = 0.0004
# 创建模型
model = Sequential()
model.add(Convolution2D(nb_filters1, conv1_size, conv1_size, border_mode="same", input_shape=(img_width, img_height, 3)))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(pool_size, pool_size)))
model.add(Convolution2D(nb_filters2, conv2_size, conv2_size, border_mode="same"))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(pool_size, pool_size), dim_ordering='th'))
model.add(Flatten())
model.add(Dense(256))
model.add(Activation("relu"))
model.add(Dropout(0.5))
model.add(Dense(classes_num, activation='softmax'))
# 编译模型
model.compile(loss='categorical_crossentropy',
optimizer=optimizers.RMSprop(lr=lr),
metrics=['accuracy'])
# 图片数据生成
train_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
# 测试数据生成
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
train_data_path,
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='categorical')
validation_generator = test_datagen.flow_from_directory(
validation_data_path,
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='categorical')
"""
Tensorboard 日志
"""
# log_dir = './tf-log/'
# tb_cb = callbacks.TensorBoard(log_dir=log_dir, histogram_freq=0)
# cbks = [tb_cb]
# 训练模型
model.fit_generator(
train_generator,
samples_per_epoch=samples_per_epoch,
epochs=epochs,
validation_data=validation_generator,
# callbacks=cbks,
validation_steps=validation_steps)
# 保存模型
target_dir = './models/'
if not os.path.exists(target_dir):
os.mkdir(target_dir)
model.save('./models/model.h5')
model.save_weights('./models/weights.h5')
# 计算程序执行时间
end = time.time()
dur = end-start
if dur < 60:
print("Execution Time:", dur, "seconds")
elif dur > 60 and dur < 3600:
dur = dur/60
print("Execution Time:", dur, "minutes")
else:
dur = dur/(60*60)
print("Execution Time:", dur, "hours")
可能出现问题:
1.Keras 安装的版本,使用pip安装即可,由于这里使用的是Anaconda,所以可以去其环境里查找未安装的版本,若出现版本不匹配问题,安装匹配版本即可
2.代码一般只会出现路径问题了多注意注意路径
注:
由于电脑不同,训练时间也不太相同,如果比较慢,多等等就好了。
如果出现此类警告,可以不用管它
对图片进行分类测试,并显示结果。
代码如下:
import os
import numpy as np
from keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array
from keras.models import Sequential, load_model
import time
import cv2
# 测试图片分类
# 记录开始时间
start = time.time()
# 相关目录:模型路径,权重路径,测试路径
model_path = r'./models/model.h5'
model_weights_path = r'./models/weights.h5'
test_path = r'E:\smartcar\tf\test2'
# 加载训练好的模型
model = load_model(model_path)
model.load_weights(model_weights_path)
# 定义图片宽和高
img_width, img_height = 150, 150
def predict(file):
"""
图片分类函数
:param file: 要分类的图片
:return: 分类结果
"""
# 加载图片
img = load_img(file, target_size=(img_width, img_height))
x = img_to_array(img)
x = np.expand_dims(x, axis=0)
# 进行分类(预测)
array = model.predict(x)
result = array[0]
print(result)
answer = np.argmax(result)
print('predicted: {}'.format(answer))
return answer
# 创建用于显示结果的窗口
cv2.namedWindow("preview", cv2.WINDOW_NORMAL)
cv2.resizeWindow("preview", 200, 200)
# 对测试目录下的所有图片文件进行分类(预测)
for i, ret in enumerate(os.walk(test_path)):
for i, filename in enumerate(ret[2]):
if filename.startswith("."):
continue
# 得到完整图片文件名
full_name = os.path.join(ret[0] , filename)
print(full_name)
# 进行分类
result = predict(full_name)
# 显示分类结果
cv2.imshow("preview", cv2.imread(full_name))
cv2.setWindowTitle("preview", str(result))
cv2.waitKey(1000)
# 计算程序执行时间
end = time.time()
dur = end-start
if dur < 60:
print("Execution Time:",dur,"seconds")
elif dur > 60 and dur<3600:
dur=dur/60
print("Execution Time:",dur,"minutes")
else:
dur=dur/(60*60)
print("Execution Time:",dur,"hours")
很多人在前两步不会有太大问题,到了这里测试可能不成功
这里出现的问题可能是:
1.测试路径中没有放测试图片
2.依旧是路径问题:
解决就看仔细了
3.一定要注意在路径前添加读写方式
如果这里不添加,那么整个测试会连最初的循环都进不去
一定要注意!
桃子找这个地方找了好久呜呜呜,老师给的例子并没有写出来,最开始我就以为是我的test_path错了导致循环进不去,经过百度,尝试多种做法,还是没法在os.walk(test_path)这里进入循环,后来终于发现了这个地方。
呜呜呜呜,搞了起码三小时,累了累了
总而言之
编程看命。
最终运行结果:
还有个小窗口(窗口名就是答案)