python+Tensorflow+CNN花朵分类

代码

实验步骤

1、首先下载数据集,存放于电脑E盘,图片路径path,e:\flowers;
2、读取数据。将图片存放在data中,标签存放在label中

#读取图片
def read_img(path):
    #os.listdir(path)表示在path路径下的所有文件和和文件夹列表
    #用cate记录五种花的文件路径
    cate=[path+x for x in os.listdir(path) if os.path.isdir(path+x)]
    imgs=[]  #存放所有的图片
    labels=[]  #图片的类别标签
    for idx,folder in enumerate(cate):
        for im in glob.glob(folder+'/*.jpg'):
            #print('reading the images:%s'%(im))#im表示某张图片的路径
            img=io.imread(im)
            img=transform.resize(img,(w,h))#图片resize为100*100
            imgs.append(img)
            labels.append(idx)
    #不用array的原因是copy时不会占用新的内存
    return np.asarray(imgs,np.float32),np.asarray(labels,np.int32)   

3、从每类花中选取部分图片可视化。设置要显示的每类花的数量show_num,获取每类花的总数量max_n。对每类花,随机生成show_num个在0,max_n-1之间的数据,表示在该类花中随机选择的图片。由于data中花是按顺序存放Dev,所以i类花的第j个花在data中的位置为i*max_n+j。调用matplotlib.pyplot显示图片。

#部分图片可视化,每种花分别选取show_num 张
###1.每类花选择show_num张图片显示
###2.获取每类花的数量max_n
###3.对每类花,随机生成show_num个在0,max_n-1之间的数据,表示该类花随机选择的图片
###由于data中花是按顺序存放,i类花的第j个在data中的位置为i*max_n+j
def show(data,label):
    show_num = 5
    plt.figure()
    max_n = np.int(data.shape[0]/5)
    for i in range(show_num):
        a=[random.randint(0,max_n) for _ in range(show_num)]
        for j in range(show_num):
            plt.subplot(show_num,show_num,show_num*i+j+1)
            plt.imshow(data[a[j]+np.int(max_n*i)-1])
            plt.axis('off')
    plt.show()

结果:
在这里插入图片描述
4、将所有图片归一化为100×100×3,打乱顺序后,选取60%作为训练集,20%为验证集,20%作为测试集。
训练集:用来训练网络参数,使得模型能够拟合数据。
验证集:调整超参数,防止模型发生过拟合,从而决定训练的结束。
测试集:用来测试模型的泛华能力,检查模型是否能很好的拟合训练过程中没有出现过的新数据,以此反应模型的真实能力。

#打乱顺序
###调用np.random.shuffle函数将有序数组变无序
###返回打乱顺序后的图片和对应的标签
def disturb(data,lable):
    num_example=data.shape[0]
    arr=np.arange(num_example)
    np.random.shuffle(arr)
    img=data[arr]
    labels=label[arr]
    return img,labels
#将所有数据分为训练集和验证集\测试集
def allocate(data,label):
    inter1 = 0.6
    inter2 = 0.8
    num_example = data.shape[0]
    s1 = np.int(num_example*inter1)
    s2 = np.int(num_example*inter2)
    x_train = data[:s1]
    y_train = label[:s1]
    x_val = data[s1:s2]
    y_val = label[s1:s2]
    x_test = data[s2:]
    y_test = label[s2:]
    return x_train,y_train,x_val,y_val,x_test,y_test    

5、构建CNN卷积网络,下图为CNN网络图。CNN模型输入为100×100,3个通道的图像;

第一层:Convolution5×5的卷积核32个,步幅为2,max_pooling卷积核2×2,Relu激活函数后,后输出第一层tensor为50×50×32。

第二层:Convolution 5×5的卷积核64个,步幅为2,max_pooling卷积核2×2,Relu激活函数后输出tensor为25×25×64

第三层:Convolution3×3的卷积核128个,步幅为2,max_pooling卷积核2×2,Relu激活函数后输出tensor为12×12×128

第四层:Convolution3×3的卷积核128个,步幅为2,max_pooling卷积核2×2,Relu激活函数后输出tensor为6×6×128

进入全连接层
第一层全连接层:1024维,将第四层输出的6×6×128tensor连接成为一个一维向量,作为该层的输入。

第二层全连接层:512维

第三层全连接层:5维

Softmax层:输出为5,即属于五类花中每类花的概率。
在训练时,从数据集中按批次取数据,设置的大小为64,训练次数分别设置为10次和20次,得到测试结果。

#-----------------构建网络----------------------
def Network():
#占位符
    #第一个卷积层(100——>50)
    conv1=tf.layers.conv2d(
          inputs=x,
          filters=32,
          kernel_size=[5, 5],
          padding="same",
          activation=tf.nn.relu,
          kernel_initializer=tf.truncated_normal_initializer(stddev=0.01))
    pool1=tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)
#第二个卷积层(50->25)
    conv2=tf.layers.conv2d(
          inputs=pool1,
          filters=64,
          kernel_size=[5, 5],
          padding="same",
          activation=tf.nn.relu,
          kernel_initializer=tf.truncated_normal_initializer(stddev=0.01))
    pool2=tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)
 #第三个卷积层(25->12)
    conv3=tf.layers.conv2d(
          inputs=pool2,
          filters=128,
          kernel_size=[3, 3],
          padding="same",
          activation=tf.nn.relu,
          kernel_initializer=tf.truncated_normal_initializer(stddev=0.01))
    pool3=tf.layers.max_pooling2d(inputs=conv3, pool_size=[2, 2], strides=2)
 #第四个卷积层(12->6)
    conv4=tf.layers.conv2d(
          inputs=pool3,
          filters=128,
          kernel_size=[3, 3],
          padding="same",
          activation=tf.nn.relu,
          kernel_initializer=tf.truncated_normal_initializer(stddev=0.01))
    pool4=tf.layers.max_pooling2d(inputs=conv4, pool_size=[2, 2], strides=2)
    re1 = tf.reshape(pool4, [-1, 6 * 6 * 128])
#全连接层
    dense1 = tf.layers.dense(inputs=re1, 
                      units=1024, 
                      activation=tf.nn.relu,
                      kernel_initializer=tf.truncated_normal_initializer(stddev=0.01),
                      kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003))
    dense2= tf.layers.dense(inputs=dense1, 
                      units=512, 
                      activation=tf.nn.relu,
                      kernel_initializer=tf.truncated_normal_initializer(stddev=0.01),
                      kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003))
    logits= tf.layers.dense(inputs=dense2, 
                        units=5, 
                        activation=None,
                        kernel_initializer=tf.truncated_normal_initializer(stddev=0.01),
                        kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003))
     return logits                                                  

6、训练模型,将训练好的模型保存在modle.ckpt中。

#训练和测试数据,可将n_epoch设置更大一些
def train(x_train,y_train,x_val,y_val,train_op,loss,acc):
    n_epoch=10
    batch_size=64
    # 用于保存和载入模型
    saver = tf.train.Saver(max_to_keep=1)
    sess=tf.InteractiveSession()  
    sess.run(tf.global_variables_initializer())
    #保存训练过程中训练损失和训练集的正确率
    Train_loss= np.zeros(n_epoch)
    Train_acc = np.zeros(n_epoch)
    #保存训练过程中验证损失和验证集的正确率
    Val_loss= np.zeros(n_epoch)
    Val_acc = np.zeros(n_epoch)
    for epoch in range(n_epoch):
        start_time = time.time()
        #training
        train_loss, train_acc, n_batch = 0, 0, 0
        for x_train_a, y_train_a in minibatches(x_train, y_train, batch_size, shuffle=True):
            _,err,ac=sess.run([train_op,loss,acc], feed_dict={x: x_train_a, y_: y_train_a})
            train_loss += err; 
            train_acc += ac; 
            n_batch += 1
        print('epoch',epoch+1)
        Train_loss[epoch] = train_loss/ n_batch
        Train_acc[epoch] = train_acc/ n_batch
        print("   train loss: %f" % Train_loss[epoch])
        print("   train acc: %f" %  Train_acc[epoch])
        #validation
        val_loss, val_acc, n_batch = 0, 0, 0
        for x_val_a, y_val_a in minibatches(x_val, y_val, batch_size, shuffle=False):
            err, ac = sess.run([loss,acc], feed_dict={x: x_val_a, y_: y_val_a})
            val_loss += err; 
            val_acc += ac; 
            n_batch += 1
        Val_loss[epoch] = val_loss/ n_batch
        Val_acc[epoch] = val_acc/ n_batch
        print("   validation loss: %f" %  Val_loss[epoch])
        print("   validation acc: %f" %  Val_acc[epoch])
    N = [i+1 for i in range(n_epoch)]
    saver.save(sess,modle_path)
    sess.close()
    return Train_loss,Train_acc,Val_loss,Val_acc,N

最终训练10次时训练集正确率达到58.82%,下图为训练损失、训练正确率、验证损失和验证集正确率随训练次数的变化。
在这里插入图片描述

7、测试模型。载入训练好的模型,读取模型参数,将测试集数据传人网络得到输出,输出与正确标签对比获得测试集正确率。

def test(x_test,y_test):
    with tf.Session() as sess:
        saver = tf.train.import_meta_graph('E:/flowers/modle.ckpt.meta')
        saver.restore(sess,tf.train.latest_checkpoint('E:/flowers/'))
        #获取默认系统图
        graph = tf.get_default_graph()
        x = graph.get_tensor_by_name("x:0")
        feed_dict = {x:x_test}
        logits = graph.get_tensor_by_name("logits_eval:0")
        #得到预测结果
        classification_result = sess.run(logits,feed_dict)
        #根据索引通过字典对应花的分类
        output = []
        output = tf.argmax(classification_result,1).eval()
        print(output)
        Real = tf.equal(output,y_test).tolist.count(True)
        test_acc = Real / x_test.shape[0]
        return test_acc

8、预测花朵类别。读取训练好的模型,输入待测试图片,最终输出花朵种类。本文从网上一共找了10张图片进行测试。

# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from skimage import io,transform                                          
def predict(img):
    with tf.Session() as sess:
        saver = tf.train.import_meta_graph('E:/flowers/modle.ckpt.meta')
        saver.restore(sess,tf.train.latest_checkpoint('E:/flowers/'))
        graph = tf.get_default_graph()
        x = graph.get_tensor_by_name("x:0")
        feed_dict = {x:img}
        logits = graph.get_tensor_by_name("logits_eval:0")
        #得到预测结果
        classification_result = sess.run(logits,feed_dict)
        output = tf.argmax(classification_result,1).eval()
        return output
imgs = []
for i in range(1,10):
    img = io.imread('e:/test/'+str(i)+'.jpg')
    img = transform.resize(img,(100,100))
    imgs.append(img)
imgs = np.asarray(imgs,np.float32)
output = predict(imgs)
#acc = test(x_test,y_test)
class_flower = ["daisy","dandelion","rose","sunflowers","tulips"]
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
print('预测结果:',output)
for i in range(9):
    plt.figure(i+1)
    img = io.imread('e:/test/'+str(i+1)+'.jpg')
    plt.imshow(img)
    plt.xlabel('预测结果为:'+class_flower[output[i]])    

结果:
在这里插入图片描述

如果这篇文章对您有帮助的话,感谢支持哦!

在这里插入图片描述

  • 4
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秃头嘤嘤魔

感谢厚爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值