作者 | 苏溪镇的水

出品 | AI科技大本营(ID:rgznai100)

在人工智能的发展越来越火热的今天,其中智能应用也在伴随着我们的生活,其中最具有代表性的便是图像识别,并且其中的应用比比皆是,如车站的人脸识别系统,交通的智能监控车牌号系统等等。而卷积神经网络作为图像识别的首选算法,对于图像的特征提取具有很好的效果,而TensorFlow作为Google的开源框架具有很好的结构化特征,而本篇文章将利用卷积神经网络算法对图像识别进行应用,开发出颜值评分器的功能。


首先我们准备训练的数据集文件保存在images文件夹下,其中的数据集如下:


其中需要训练的数据集的标签保存在Excel中,为All_Ratings.xlsx,即标签就为图像的颜值评分,其中的数据如下:


接着我们新建一个python文件为_input_data.py,即用来读取数据集以达到训练的目的。这里和卷积神经网络无关,故我仅仅大概说明一下并加以附上代码,其中要导入的模块代码:


import numpy as np
import tensorflow as tf
import os
import cv2
import matplotlib.pyplot as plt
import os
from PIL import Image
import pandas as pd

然后定义一个函数用来获取文件夹下的图片,并定义四个数组分别为meis,chous,chous_label,meis_label这几个数组分别保存着美人的图片名及路径,丑人的图片名及路径,丑人的标签设为0保存到chous_label这个数组中,美人的标签设为1保存在meis_label。代码如下:


def get_files(file_dir):
    chous = []
    meis = []
    chous_label = []
    meis_label = []
    img_dirs = os.listdir(file_dir)#读取文件名下所有!目录名(列表形式)
    labpath = "F:/python练习/test1/All_Ratings.xlsx"
    date = pd.read_excel(labpath)
    filenames = date['Filename']
    label = date['Rating']
    for i in range(filenames.shape[0]):
            if int(label[i])>3:
                    meis_label.append(1)
                    meis.append(file_dir + filenames[i]) 
            else:
                    chous_label.append(0)
                    chous.append(file_dir + filenames[i]) 
    img_list = np.hstack((chous, meis))#列表(字符串形式)
    label_list = np.hstack((chous_label, meis_label))#列表(整数形式)
    return img_list, label_list

接着再定义一个函数用来获取图片的长和宽,一次训练的个数等等。具体代码如下:


def get_batch(image, label, image_w, image_h, batch_size, capacity):#capacity: 队列中 最多容纳图片的个数
    input_queue = tf.train.slice_input_producer([image, label])#tf.train.slice_input_producer是一个tensor生成器,作用是
    # 按照设定,每次从一个tensor列表中按顺序或者随机抽取出一个tensor放入文件名队列。
    label = input_queue[1]
    img_contents = tf.read_file(input_queue[0])#一维
    image = tf.image.decode_jpeg(img_contents, channels=3)#解码成三维矩阵
    image = tf.image.resize_image_with_crop_or_pad(image, image_w, image_h)
    image = tf.cast(image, tf.float32)
    image = tf.image.per_image_standardization(image)

# 生成批次  num_threads 有多少个线程根据电脑配置设置
    image_batch, label_batch = tf.train.batch([image, label], batch_size=batch_size, num_threads=64, capacity=capacity)
return image_batch, label_batch

接着下面是卷积神经网络的算法部分,我们需要建立一个文件名为model.py的文件,用来保存算法结构参数,首先导入TensorFlow框架,代码为:


import tensorflow as tf

首先简单说明下这篇文章所用的卷积神经网络的原理和结构:其中第一层为输入层,即可以读取图像的各点像素值保存在矩阵中,接着为卷积一层我把它命名为“conv1”,即为第一个卷积层,即利用我定义的卷积核来乘上原来输入层的矩阵,而所谓的卷积核也就是一个矩阵,而其中相乘包括步长等等这里不详细说明。

接着接上一个池化层命名为“pooling1_lrn”,其主要目的是降采样,即将其中图像的像素矩阵变小。接着再接上卷积二层,命名为“conv2”,每一层的输入层为上一层的输出值,再接上池化二层“pooling2_lrn”,同样目的降采样,接着接上全连接层中的两个隐藏层名为“local3”,和“local4”,最后输出层接的是softmax激活函数,为二分类的激活函数,主要原因是我需要的结果是美和丑两种结果,详细代码见下:

import tensorflow as tf

#卷积神经网络提取特征
def inference(image, batch_size, n_classes):
    #第一个卷积层
    with tf.variable_scope("conv1") as scope:#课本108,variable_scope控制get_variable是获取(reuse=True)还是创建变量
        weights = tf.get_variable("weights", shape=[3,3,3,16], dtype=tf.float32,
                                  initializer=tf.truncated_normal_initializer(stddev=0.1, dtype=tf.float32))
        biases = tf.get_variable("biases", shape=[16], dtype=tf.float32,
                                 initializer=tf.constant_initializer(0.1))
        conv = tf.nn.conv2d(image, weights, strides=[1,1,1,1], padding="SAME")
        pre_activation = tf.nn.bias_add(conv, biases)
        conv1 = tf.nn.relu(pre_activation, name=scope.name)
    #池化层,降采样
    with tf.variable_scope("pooling1_lrn") as scope:
        pool1 = tf.nn.max_pool(conv1, ksize=[1,3,3,1], strides=[1,2,2,1], padding="SAME", name="pooling1")
        norm1 = tf.nn.lrn(pool1, depth_radius=4, bias=1.0, alpha=0.001/9.0,beta=0.75, name="norm1")#局部响应归一化??????
    with tf.variable_scope("conv2") as scope:
        weights = tf.get_variable("weights", shape=[3,3,16,16], dtype=tf.float32,
                                  initializer=tf.truncated_normal_initializer(stddev=0.1, dtype=tf.float32))
        biases = tf.get_variable("biases", shape=[16], dtype=tf.float32,
                                 initializer=tf.constant_initializer(0.1))
        conv = tf.nn.conv2d(norm1, weights, strides=[1,1,1,1], padding="SAME")
        pre_activation = tf.nn.bias_add(conv, biases)
        conv2 = tf.nn.relu(pre_activation, name=scope.name)

with tf.variable_scope("pooling2_lrn") as scope:
        norm2 = tf.nn.lrn(conv2, depth_radius=4, bias=1.0, alpha=0.001/9.0,beta=0.75, name="norm2")
        pool2 = tf.nn.max_pool(norm2, ksize=[1,3,3,1], strides=[1,2,2,1], padding="SAME", name="pooling2")
    #全连接层
    with tf.variable_scope("local3") as scope:
        reshape = tf.reshape(pool2, shape=[batch_size, -1])
        dim = reshape.get_shape()[1].value
        weights = tf.get_variable("weights", shape=[dim, 128], dtype=tf.float32,
                                  initializer=tf.truncated_normal_initializer(stddev=0.005, dtype=tf.float32))
        biases = tf.get_variable("biases", shape=[128], dtype=tf.float32, initializer=tf.constant_initializer(0.1))
    local3 = tf.nn.relu(tf.matmul(reshape, weights) + biases, name=scope.name)

with tf.variable_scope("local4") as scope:
        weights = tf.get_variable("weights", shape=[128, 128], dtype=tf.float32,
                                  initializer=tf.truncated_normal_initializer(stddev=0.005, dtype=tf.float32))
        biases = tf.get_variable("biases", shape=[128], dtype=tf.float32, initializer=tf.constant_initializer(0.1))
    local4 = tf.nn.relu(tf.matmul(local3, weights) + biases,name="local4")
    #softmax二分类
    with tf.variable_scope("softmax_linear") as scope:
        weights = tf.get_variable("weights", shape=[128, n_classes], dtype=tf.float32,
                                  initializer=tf.truncated_normal_initializer(stddev=0.005, dtype=tf.float32))
        biases = tf.get_variable("biases", shape=[n_classes], dtype=tf.float32, initializer=tf.constant_initializer(0.1))
    softmax_linear = tf.nn.relu(tf.matmul(local4, weights) + biases,name="softmax_linear")

return softmax_linear

def loss(logits, labels):#输出结果和标准答案
    with tf.variable_scope("loss") as scope:
        cross_entropy= tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=labels, name="entropy_per_example")
        loss = tf.reduce_mean(cross_entropy)
        tf.summary.scalar(scope.name +"/loss",loss)#对标量数据汇总和记录使用tf.summary.scalar
    return loss

def training(loss, learning_rate):
    with tf.name_scope("optimizer"):
        global_step = tf.Variable(0, name="global_step", trainable=False)#定义训练的轮数,为不可训练的参数
        optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
        train_op= optimizer.minimize(loss, global_step=global_step)
        #上两行等价于train_op = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss,global_step=global_step)
    return train_op

def evalution(logits, labels):
    with tf.variable_scope("accuracy") as scope:
        correct = tf.nn.in_top_k(logits, labels, 1)#下面
        correct = tf.cast(correct, tf.float16)
        accuracy = tf.reduce_mean(correct)
        tf.summary.scalar(scope.name+"/accuracy", accuracy)#用来显示标量信息
    return accuracy

"""

top_1_op取样本的最大预测概率的索引与实际标签对比,top_2_op取样本的最大和仅次最大的两个预测概率与实际标签对比,

如果实际标签在其中则为True,否则为False。

"""

其中定义的几个函数是为了训练使用而定义的,loss函数计算每次训练的损失值,training函数用来加载训练,包括损失值和学习率,evalution用来评估每次训练的精准度。

接着开始模型的训练,新建一个python文件名为“training.py”,其中设定常量:


N_CLASSES = 2
IMG_W = 350
IMG_H = 350
BATCH_SIZE = 32
CAPACITY = 256
STEP =500    #训练步数应当大于10000
LEARNING_RATE = 0.0001

分别表示结果输出为二分类(美和丑),图片的长和宽,每次训练的图片数目,训练容量,训练次数,学习率;接着将前面建立的python文件中的函数直接拿来使用,首先依旧是导入库以及前面建立的两个python文件:


import tensorflow as tf
import numpy as np
import os
import _input_data
import model

接着定义训练数据所保存的路径,模型保存的路径,其中应注意模型保存的路径中不能出现中文,否则报错;接着使用函数训练。详细代码如下:


x = tf.placeholder(tf.float32, shape=[None,129792])
y_ = tf.placeholder(tf.float32, shape=[None, 5])

def run_training():
    train_dir = "F:/python练习/test1/Images/"
    log_train_dir = "F:/train_savenet/"

train,train_labels = _input_data.get_files(train_dir)
    train_batch, train_label_batch = _input_data.get_batch(train, train_labels, IMG_W,IMG_H,BATCH_SIZE,CAPACITY)

train_logits= model.inference(train_batch, BATCH_SIZE, N_CLASSES)
    train_loss= model.loss(train_logits, train_label_batch)
    train_op = model.training(train_loss, LEARNING_RATE)
    train_acc = model.evalution(train_logits, train_label_batch)
    summary_op = tf.summary.merge_all()#merge_all 可以将所有summary全部保存到磁盘,以便tensorboard显示。
    # 一般这一句就可显示训练时的各种信息。

sess = tf.Session()
    train_writer  =tf.summary.FileWriter(log_train_dir, sess.graph)#指定一个文件用来保存图
    saver = tf.train.Saver()

sess.run(tf.global_variables_initializer())
    #  Coordinator  和 start_queue_runners 监控 queue 的状态,不停的入队出队
    coord = tf.train.Coordinator()#https://blog.csdn.net/weixin_42052460/article/details/80714539
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)

try:
        for step in np.arange(STEP):
            if coord.should_stop():
                break
            _, tra_loss, tra_acc = sess.run([train_op, train_loss, train_acc])
            if step % 4 == 0 or (step + 1) == STEP:
                # 每隔2步保存一下模型,模型保存在 checkpoint_path 中
                checkpoint_path = os.path.join(log_train_dir, "model.ckpt")
                saver.save(sess, checkpoint_path, global_step=step)
    except tf.errors.OutOfRangeError:
        print('Done training -- epoch limit reached')

finally:
        coord.request_stop()
    coord.join(threads)
    sess.close()

run_training()

训练过程如图:

训练完毕后,会形成一些训练出来模型文件,可以直接拿来使用,这时候建立一个python文件名为“predict.py”用来使用模型,这部分不是重点,给出代码和结果即可:


# -*- coding: utf-8 -*-
import tensorflow as tf
from PIL import Image
import numpy as np
import os
import model
import matplotlib.pyplot as plt
import _input_data
from matplotlib import pyplot
from matplotlib.font_manager import FontProperties

def  get_one_img(test):#从指定目录中选取一张图片
    file = os.listdir(test)#os.listdir()返回指定目录下的所有文件和目录名。
    n = len(file)
    ind = np.random.randint(0, n)
    img_dir = os.path.join(test, file[ind])#判断是否存在文件或目录name
    global image1
    image1= Image.open(img_dir)
    #plt.imshow(image)
    #plt.show()
    image = image1.resize([350, 350])
    image = np.array(image)
    return image

def evaluate_one_img():
    test = "F:/python练习/test1/Images/"
    test_array = get_one_img(test)

with tf.Graph().as_default():#https://www.cnblogs.com/studylyn/p/9105818.html
        BATCH_SIZE = 1
        N_CLASSES = 2
        image = tf.cast(test_array, tf.float32)
        image = tf.image.per_image_standardization(image)
        image = tf.reshape(image,[1,350,350,3])
        logit = model.inference(image, BATCH_SIZE, N_CLASSES)
        logit = tf.nn.softmax(logit)

x =tf.placeholder(tf.float32, shape =[350,350,3])

log_test_dir = 'F:/train_savenet/'
        saver = tf.train.Saver()
        global title
        with tf.Session() as sess:
            print("从指定路径中加载模型。。。")
            #将模型加载到sess中
            ckpt = tf.train.get_checkpoint_state(log_test_dir)
            if ckpt and ckpt.model_checkpoint_path:#https://blog.csdn.net/u011500062/article/details/51728830/
                global_step  = ckpt.model_checkpoint_path.split("/")[-1].split("-")[-1]
                saver.restore(sess, ckpt.model_checkpoint_path)
                print("模型加载成功,训练的步数为 "+global_step)
            else:
                print("模型加载失败,文件没有找到。")

#将图片输入到模型计算
            prediction = sess.run(logit, feed_dict={x: test_array})
            max_index = tf.argmax(prediction) # 将图片输入到模型计算
            if float(prediction[:, 0])>0.5:
                print('丑的概率 %.6f' %prediction[:, 0])
                print("丑")
                title=u'丑'+str(prediction[:, 0]*100)
            else:
                print('美的概率 %.6f' %prediction[:, 1])
                print("美")
                title=u'美'+str(prediction[:, 1]*100)
# 测试
evaluate_one_img()
imgplot = plt.imshow(image1)
myfont = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=15)
plt.title(title,fontproperties=myfont)
plt.show()

最终拿一个图片来实验的结果如下:


由此可见模型基本正确,也可以知道卷积神经网络对于图像特征提取比较擅长。

(*本文为AI科技大本营投稿文章,转载请微信联系 1092722531

精彩推荐

2019 中国大数据技术大会(BDTC)再度来袭!豪华主席阵容及百位技术专家齐聚,15 场精选专题技术和行业论坛,超强干货+技术剖析+行业实践立体解读,深入解析热门技术在行业中的实践落地。6.6 折票限时特惠(立减1400元),学生票仅 599 元!

推荐阅读

美还是丑?这有一个CNN开发的颜值评分器 | 实战相关推荐

  1. 掌声送给TensorFlow 2.0!用Keras搭建一个CNN | 入门教程

    作者 | Himanshu Rawlani 译者 | Monanfei,责编 | 琥珀 出品 | AI科技大本营(id:rgznai100) 2019 年 3 月 6 日,谷歌在 TensorFlow ...

  2. 一个想法--开发与业务,我们互相依赖

    一个想法--开发与业务,我们互相依赖 编程之道很多人都读了,这位大师真是会利用中国阴阳学,但是中心思想就是工具就是工具,不是思想,经常听人们说,think in 什么,也是,如果单抱着什么编程实例也没 ...

  3. 打通C/4HANA和S/4HANA的一个原型开发:智能服务创新案例

    今年6月SAP发布C/4HANA之后,有顾问朋友们在微信公众号后台留言,询问C/4HANA如何同SAP的数字化核心S/4HANA系统结合起来,从而打通企业的前后端业务,帮助企业实现数字化转型. 有的顾 ...

  4. 作为一个web开发人员,哪些技术细节是在发布站点前你需要考虑到的

    前日在cnblogs上看到一遍文章<每个程序员都必读的12篇文章>,其中大多数是E文的. 先译其中一篇web相关的"每个程序员必知之WEB开发". 原文: http:/ ...

  5. 一个SAP开发人员的2018年终总结

    我是SAP成都研究院的Jerry Wang,我喂自己袋盐. 时间过得真快,2017年发生的事情还历历在目,一转眼,2018年又马上要结束了. Jerry惊恐地发现,随着年龄的增长,时光流逝的速度仿佛有 ...

  6. SAP Business ByDesign 和支付宝与钉钉集成的一个原型开发案例

    原文:Doing Business on the Go – Invoice to Cash the China Way (PoC) 众所周知,中国移动应用市场具有如下特点: 腾讯和阿里巴巴的多用途平台 ...

  7. 一个 SAP 开发工程师十余年的技术写作之路回顾

    这是 Jerry 2021 年的第 31 篇文章,也是汪子熙公众号总共第 307 篇原创文章. 本文目录 汪子熙公众号的风格定位 为什么我会开始在微信公众号上书写技术文章 我的写作素材从哪里来 坚持了 ...

  8. 飞鸽传书2007 一个自己开发的软件

    CSDN下载频道上有我的软件,今天来说是那时候的开发过程,这个软件我自己是很喜欢的,写他的时候,是非常努力的,力求完美.所以,发布的时候基本上是自己最满意的了. 飞鸽传书2007 下载地址:http: ...

  9. 一个Web开发的客户端基础技术测试Demo

    最近参加了一个Web开发的客户端基础技术测试,虽然对于做前台开发的程序员来说比较简单,但对于一直做后台代码编写的程序员想掌握前台开发的基础来说,应该是一个比较好的Demo.对于Web初学者来说,也是一 ...

  10. pytorch学习笔记(2):在MNIST上实现一个CNN

    参考文档:https://mp.weixin.qq.com/s/1TtPWYqVkj2Gaa-3QrEG1A 这篇文章是在一个大家经常见到的数据集 MNIST 上实现一个简单的 CNN.我们会基于上一 ...

最新文章

  1. react中使用create-react-app创建项目执行函数两次
  2. 【C 语言】指针数据类型 ( 指针类型变量 | 使用 * 操作内存 )
  3. mysql创建反弹函数,MySql创建函数
  4. 坑爹的日志无法按天切割问题
  5. c语言编写的每个函数都可以进行独立的编译,2017年辽宁师范大学计算机与信息技术学院836C语言程序设计考研冲刺密押题...
  6. django、tornado、flask对比
  7. 计算机桌面工具栏,win7电脑计算机界面菜单工具栏不见了怎么办?
  8. 电脑DIY基本知识扫盲!图文并茂!
  9. 中班机器人教室设计方案_中班美术教案机器人
  10. 股利折现模型详解-股票定价-财务管理(七)
  11. 工序作业指导书怎么做?如何制作工序作业指导书?
  12. #python对数列的进行排列
  13. 求这样一个三位数,该三位数等于其每位数字的阶乘之和
  14. GitHub 终端面基交友的新神器
  15. 正弦值、余弦值和正切值
  16. css 上下布局 flex,Css Flex布局
  17. 如何在Windows命令行中使用Unicode字符?
  18. Android 集成FaceBook广告
  19. Day55-每日一道Java面试题-Java 面向对象编程三大特性: 封装 继承 多态
  20. 只需64MB优盘+90分钟nbsp;教你如何全面…

热门文章

  1. ohoTips - 最屌的消息弹窗工具!
  2. 利用黎曼几何分析EEG信号(四):集论初步与拓扑空间初步
  3. 解决:vue组件顶部留有空白问题
  4. 武林传奇之七剑下天山java游戏开发商_武林传奇2之七剑下天山的配方
  5. java毕业设计_基于android的二手书城app的设计与实现
  6. iOS 环信移动客服接入
  7. python中pd是什么意思_python pd
  8. 微信商家转账到零钱 V3(JAVA)转账与查询
  9. ocpc php,oCPC匹配词很乱怎么办?| SEM问答
  10. Win下VS2019配置PCL点云库总结