keras-图像分类(内有详细代码注释)

285 阅读4分钟

目录

数据集

数据集:Animals10
十种动物:狗,猫,马,大象,蝴蝶,鸡,牛,羊,蜘蛛,松鼠
train:val:test=3:1:1

环境

Anaconda4.2.0(python3.5.2)
Keras 2.1.3
Tensorflow-gpu 1.4.0
Pillow 5
H5py 2.7.0(h5py快速入门指南https://www.jianshu.com/p/a6328c4f4986)
Numpy 1.16.3
Pycharm

1.图片预处理

写完之后先执行让它操作一波

统一图片类型

import os

def ranamesJPG(filepath, kind):
    images = os.listdir(filepath)
    for name in images:
        os.rename(filepath+name, filepath+kind+'_'+name.split('.')[0]+'.jpg')
        print(name)
        print(name.split('.')[0])
ranamesJPG('./224/猫/','7')

统一图片大小标签

import os
from PIL import Image

def convertjpg(jpgfile,outdir,width=112,height=112):
    img = Image.open('./test/'+jpgfile)
    try:
        new_img = img.resize((width, height), Image.BILINEAR)
        new_img.save(os.path.join(outdir, os.path.basename(jpgfile)))
        #print(type(new_img))
        #new_img的类型'PIL.Image.Image'
    except Exception as e:
        print(e)
for jpgfile in os.listdir('./test/'):#jpgfile读取文件夹中图片的名字,类型是str
    convertjpg(jpgfile, "./test1/")

2.模型训练

import os
from PIL import Image
import numpy as np
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.optimizers import SGD, RMSprop, Adam
from keras.layers import Conv2D, MaxPooling2D
 
#-----------------------将训练集图片转换成数组----------------------
ima1 = os.listdir('./train')#将train文件夹中的文件读取出来
def read_image1(filename):#def xxx( ): 是定义函数
    img = Image.open('./train/'+filename).convert('RGB')
    #图片赋给img这个对象
return np.array(img)#图片转化为np类型数组
 
x_train = []
 
for i in ima1:#循环所有train下面的图片
	x_train.append(read_image1(i))#将上面转换成np类型的数组放在x_train中
x_train = np.array(x_train)#将x_train转换成np类型的数组
#----------------------根据训练集文件名提取标签----------------------
y_train = []
for filename in ima1:
y_train.append(int(filename.split('_')[0]))
#读取下划线之前的数字,再将它转换成int类型的,加入到y_train中
#filename.split('_')[0]得到第一个_之前的内容
#filename.split('_')[1]得到第一个_和第二个o之间的内容
y_train = np.array(y_train)#y_train转化转化成np类型的数组
#-----------------------将测试集图片转化成数组-----------------------
ima2 = os.listdir('./test')
def read_image2(filename):
    img = Image.open('./test/'+filename).convert('RGB')
    return np.array(img)
 
x_test = []
 
for i in ima2:
    x_test.append(read_image2(i))
 
x_test = np.array(x_test)

#-----------------------根据测试集文件名提取标签--------------------
y_test = []
for filename in ima2:
    y_test.append(int(filename.split('_')[0]))
 
y_test = np.array(y_test)
#--------------------------将标签转换格式----------------------------
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
 
#-------------------将特征点从0~255转换成0~1提高特征提取精度---------------
'''
https://blog.csdn.net/m0_37678226/article/details/89635703
最常见的对图像预处理方法有以下几种:
(1)去均值
(2)归一化处理
(3)正常白化处理又叫图像标准化处理
(4)PCA
 '''
# 归一化处理
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
 
#----------------------------搭建卷积神经网络----------------------------
model = Sequential()
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(100, 100, 3)))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
 
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
 
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(4, activation='softmax'))# 你一共分多少类,这里猫四类
 
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True) #随机梯度下降
#sgd = SGD(lr=learning_rate, decay=learning_rate/nb_epoch, momentum=0.9, nesterov=True)
#lr:大于0的浮点数,学习率;momentum:大于0的浮点数,动量参数;decay:大于0的浮点数,每次更新后的学习率衰减值;nesterov:布尔值,确定是否使用Nesterov动量
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])#编译
#绝对叉熵约束
'''
可以使用 compile(self, optimizer, loss, metrics=None, sample_weight_mode=None, weighted_metrics=None, target_tensors=None) 来完成配置
compile() 主要接收前三个参数:
loss:字符串类型,用来指定损失函数,如:categorical_crossentropy,binary_crossentropy
optimizer:字符串类型,用来指定优化方式,如:rmsprop,adam,sgd
metrics:列表类型,用来指定衡量模型的指标,如:accuracy
'''
hist = model.fit(x_train, y_train, batch_size = 32, epochs = 200,verbose = 1,validation_data = (x_test, y_test))
#开始训练,返回train的loss和acc
#一次处理多少张图片,计算机性能好的话可以调高
#一共训练多少次
#返回test的loss acc
#fit()用于使用给定输入训练模型.(返回训练集loss、acc)
#predict()用于实际预测.它为输入样本生成输出预测.
#evaluate()用于评估已经训练过的模型.返回损失值&模型的度量值.
 
model.save_weights('./cat/cat_weights.h5', overwrite=True)
#找到的拟合的很好的参数保存成.h5
score = model.evaluate(x_test, y_test, batch_size = 32,verbose=0)
#测试集输入到卷积神经网络中
#verbose = 0 为不在标准输出流输出日志信息,verbose = 1 为输出进度条记录,verbose = 2 为每个epoch输出一行记录
 
model.evaluate
输入数据和标签,输出损失和精确度.
	# 评估模型,不输出预测结果
	loss,accuracy = model.evaluate(X_test,Y_test)
	print('test loss',loss)
	print('accuracy',accuracy)
 
print(score)
#后两句为了打印这个
#---------------------------------画图--------------------------------
plt.figure()# 创建一个绘图窗口
acc = hist.history['acc']
val_acc = hist.history['val_acc']
loss = hist.history['loss']
val_loss = hist.history['val_loss']
epochs = range(len(acc))
plt.plot(epochs, acc, 'y-', label='Training acc')  
#'b-'为画蓝色线 ‘r-’红色‘y-’黄色 ‘g-’绿色
plt.plot(epochs, val_acc, 'r-', label='Validation acc')
plt.plot(epochs, loss, 'b-', label='Training loss')
plt.plot(epochs, val_loss, 'g-', label='Validation loss')
plt.title('acc & loss')#标题
plt.legend()  # 绘制图例,默认在右上角
plt.show()

3.预测

import os
from PIL import Image
import numpy as np
import copy
import random

from keras.optimizers import SGD
from keras.applications.vgg16 import VGG16
from keras.backend import clear_session

'''
单个图片预测
def prepicture(picname):
    img = Image.open('./pic/' + picname)
    new_img = img.resize((224, 224), Image.BILINEAR)
    new_img.save(os.path.join('./pic/', os.path.basename(picname)))

def read_image2(filename):
    img = Image.open('./pic/'+filename).convert('RGB')
    return np.array(img)

prepicture('0_OIP-sjeHzofdssb2vtWhVM8PGQHaFj.jpg')
x_test = []

x_test.append(read_image2('0_OIP-sjeHzofdssb2vtWhVM8PGQHaFj.jpg'))

x_test = np.array(x_test)

x_test = x_test.astype('float32')
x_test /= 255

clear_session() #清理session反复识别注意

predict = model.predict(x_test)
predict=np.argmax(predict,axis=1)
print(predict)
'''
random.seed(0)
clear_session() #清理session反复识别注意
model = VGG16(include_top = True,classes = 4,weights = None)
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
model.load_weights ("animals_weights_qy12_pca.h5")
daxiang=0
songshu=0
niu=0
gou=0
#多个图片预测
imgs = os.listdir('./pic/')
for jpg in imgs:
    img = Image.open('./pic/'+jpg)
    img = img.resize((224,224))
    img = np.array(img)
    img = img/255
    img = img.reshape(-1,224,224,3)

    pr = model.predict(img)[0]
    pr = np.argmax(pr, axis=-1)
    if pr==0:
        daixiang=daxiang+1
    elif pr==1:
        songshu = songshu + 1
    elif pr == 2:
        niu = niu+1
    else:
        gou=gou+1
        '''
    target = ['大象', '松鼠', '牛', '狗']
    print(target[pr])
    '''
print(daxiang,songshu,niu,gou)