Tensorflow框架搭建卷积神经网络进行五种花的分类

数据集:
五种花:daisy、dandelion、roses、sunflowers、tulips
Tensorflow框架搭建卷积神经网络进行五种花的分类_第1张图片
数据集下载:http://download.tensorflow.org/example_images/flower_photos.tgz

读取并随机打乱数据集: read_img.py

# -*- coding: utf-8 -*-
"""
Created on Wed Jun 26 09:23:46 2019

@author: ZQQ
"""

import numpy as np
import os
import glob
from skimage import transform,io
import random

# 定义超参数
w = 100 
h = 100

#### 定义读取图片的函数:read_img()
def read_img(path):
    data_list = [path + x for x in os.listdir(path) if os.path.isdir(path + x)] # 所有图片分类目录
    imgs = [] # 定义一个imgs空列表,存放遍历读取的图片
    labels = [] # 定义一个labels空列表,存放图片标签
    for idx, folder in enumerate(data_list):  # 遍历每个文件夹中的图片,idx表示
        for im in glob.glob(folder + '/*.jpg'):  # *:匹配0个或多个字符
            print('reading the images:%s' % (im))
            img = io.imread(im)
            img = transform.resize(img, (w, h)) # 将所有图片的尺寸统一为:100*100(宽度*高度)
            with open('datasets_name.txt','a') as f:
                f.write(folder+im+'_'+str(idx)+'\n')
            imgs.append(img) # 遍历后更改尺寸后的图片添加到imgs列表中
            labels.append(idx) # 遍历后更改尺寸后的图片标签添加到labels列表中
    return np.asarray(imgs, np.float32), np.asarray(labels, np.int32) # np.float32是类型 后面两个变量是没有进行np.asarray

# np.asarray 和 np.array
# np.array与np.asarray功能是一样的,都是将输入转为矩阵格式。
# 主要区别在于 np.array(默认情况下)将会copy该对象,而 np.asarray除非必要,否则不会copy该对象。

### 定义随机打乱数据集的函数:shuffle_data()
def shuffle_data(data,label):
    # 打乱顺序
    data_size = data.shape[0] # 数据集个数
    arr = np.arange(data_size) # 生成0到datasize个数
    np.random.shuffle(arr) # 随机打乱arr数组
    data = data[arr] # 将data以arr索引重新组合
    label = label[arr] # 将label以arr索引重新组合
    
#    # 打乱数据顺序的另一种方法,当然还有其他的方法
#    index = [i for i in range(len(data))]
#    random.shuffle(index)
#    data = data[index]
#    label = label[index]
    
    # 将所有数据分为训练集和验证集
    ratio = 0.8 # 训练集比例
    num = np.int(len(data) * ratio)
    x_train = data[:num]
    y_train = label[:num]
    x_val = data[num:]
    y_val = label[num:]
    
    return x_train, y_train, x_val, y_val

#path = 'flower_photos/' # 所有图片的总路径(目录)
#data, label = read_img(path)

搭建卷积神经网络:cnn.py

# -*- coding: utf-8 -*-
"""
Created on Wed Jun 26 16:38:15 2019

@author: ZQQ

tools:Pycharm

用tensorflo框架搭建一个卷积神经网络
参考:
https://www.cnblogs.com/ansang/p/9164805.html

数据:http://download.tensorflow.org/example_images/flower_photos.tgz

"""

import tensorflow as tf

# 定义批量标准化函数,有效防止了梯度消失和爆炸,还加速了收敛
# def batch_norm(x, momentum=0.9, epsilon=1e-5, train=True, name='bn'):
#     return tf.layers.batch_normalization(x,
#                                          momentum=momentum,
#                                          epsilon=epsilon,
#                                          scale=True,
#                                          training=train,
#                                          name=name)

def simple_net(x):
    ### 卷积,池化
    # 第一层卷积层(100->50)
    conv1 = tf.layers.conv2d(inputs=x,
                             filters=32,
                             #kernel_size=[3,3], # kernel_size = [5,5] 换不同的核大小,查看效果
                             kernel_size = [5,5],
                             padding="same",
                             activation=tf.nn.relu,
                             kernel_initializer=tf.truncated_normal_initializer(stddev=0.01))  # padding="same",卷积层不改变图片大小
    #conv1 = batch_norm(conv1, name="pw_bn1")  # 加入批量标准化
    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))
    #conv2 = batch_norm(conv2, name="pw_bn2")
    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))
    #conv3 = batch_norm(conv3, name="pw_bn3")
    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))
    #conv4 = batch_norm(conv4, name="pw_bn4")
    pool4 = tf.layers.max_pooling2d(inputs=conv4,
                                    pool_size=[2,2],
                                    strides=2)

    rel = tf.reshape(pool4,[-1, 6 * 6 * 128])

    # 防止过拟合,加入dropout
    #dropout = tf.layers.dropout(inputs=rel, rate=0.5)

    ### 全连接层
    dense1 = tf.layers.dense(inputs=rel,
                             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, # 5个类
                             activation=None,
                             kernel_initializer=tf.truncated_normal_initializer(stddev=0.01),
                             kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003))

    #pred = tf.nn.softmax(logits, name='prob') # softmax处理
    #return logits, pred
    return logits

### 四个卷积层,两个全连接层,一个softmax层组成。
### 在每一层的卷积后面加入batch_normalization, relu, 池化
### batch_normalization层很好用,加了它之后,有效防止了梯度消失和爆炸,还加速了收敛。

定义一个批量取数据的函数:batch_get_data.py

# -*- coding: utf-8 -*-
"""
Created on Wed Jun 26 21:23:56 2019

@author: ZQQ
"""

import numpy as np

# 定义一个函数,按批次取数据
def minibatches(inputs=None, targets=None, batch_size=None, shuffle=False):
    assert len(inputs) == len(targets)
    if shuffle:
        indices = np.arange(len(inputs))
        np.random.shuffle(indices)
    for start_idx in range(0, len(inputs) - batch_size + 1, batch_size):
        if shuffle:
            excerpt = indices[start_idx:start_idx + batch_size]
        else:
            excerpt = slice(start_idx, start_idx + batch_size)
        yield inputs[excerpt], targets[excerpt]

实验结果:
进行100次epoch
Tensorflow框架搭建卷积神经网络进行五种花的分类_第2张图片
Tensorflow框架搭建卷积神经网络进行五种花的分类_第3张图片
Tensorflow框架搭建卷积神经网络进行五种花的分类_第4张图片
Tensorflow框架搭建卷积神经网络进行五种花的分类_第5张图片
总结:val loss 来看,有点过拟合,精度没有得到大的提高,后期加入dropout再进一步查看实验效果。
还可以进行批量标准化,加速收敛,并且可以防止梯度消失或者梯度爆炸。
以及加入softmax处理等。
独立测试:test_independent.py
训练得到模型保存后,加载,测试输入的图片

# -*- coding: utf-8 -*-
"""
Created on Sat Jun 29 14:57:15 2019

@author: ZQQ

参考:
https://www.cnblogs.com/ansang/p/9164805.html
"""

import numpy as np
import tensorflow as tf
from PIL import Image, ImageDraw, ImageFont
from models import cnn
import matplotlib.pyplot as plt

# 将所有的图片resize成100*100
w = 100
h = 100
c = 3

classes = ['daisy','dandelion','roses','sunflowers','tulips']
image_test = Image.open('flowers_photos_independent/test1.jpg')

plt.imshow(image_test)
plt.show()

resized_image = image_test.resize((w, h), Image.BICUBIC)
image_data = np.array(resized_image, dtype='float32')

imgs_holder = tf.placeholder(tf.float32, shape=[1, w, h, c])

logits = cnn.simple_net(imgs_holder)

saver = tf.train.Saver()
ckpt_dir = 'result/model_save/'

with tf.Session() as sess:
    ckpt = tf.train.get_checkpoint_state(ckpt_dir)
    saver.restore(sess, ckpt.model_checkpoint_path)
    classes_ = sess.run(logits,feed_dict={ imgs_holder: np.reshape(image_data , [1,w, h, c])})

num = np.argmax(classes_)
print('class is :',classes[int(num)],'  Probability is :',classes_[0][int(num)])

项目整体结构:
Tensorflow框架搭建卷积神经网络进行五种花的分类_第6张图片
代码后期,将移植到github上,尽情期待。
坚持,感恩社会,努力,加油!

注:还可以用几种比较典型的卷积神经网络进行实现,比如lenet、alexnet、vggnet等等。

源码:
https://github.com/AugustMe/TensorFlow-Learn/tree/master/FlowersImageClassify

你可能感兴趣的:(python,图像处理,TensorFlow)