Python-Level5-day12:全连接层实现手写体识别项目,面向对象实现基于卷积神经网络的服饰识别项目

 

# 01_mnist_demo.py
# 利用神经网络实现手写体识别(10分类的图像分类问题)
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import pylab

# 第一步:数据准备(从数据集中读取)
mnist = input_data.read_data_sets("MNIST_data/",  # 数据集路径
                                  one_hot=True)  # 标签独热编码
x = tf.placeholder(tf.float32, [None, 784])  # 图像数据,N行784列
y = tf.placeholder(tf.float32, [None, 10])  # 标签,N行10列

# 第二步:定义模型(神经网络)
w = tf.Variable(tf.random_normal([784, 10]))  # 权重,随机值
b = tf.Variable(tf.zeros([10]))  # 偏置, 初始值为0
pred_y = tf.nn.softmax(tf.matmul(x, w) + b)  # 神经网络

# 第三步:定义损失函数、优化器
cross_entropy = -tf.reduce_sum(y * tf.log(pred_y),
                               reduction_indices=1)  # 指定维度
cost = tf.reduce_mean(cross_entropy)  # 求均值

lr = 0.01  # 学习率
optimizer = tf.train.GradientDescentOptimizer(lr).minimize(cost)

# 第四步:模型训练、评估、保存
batch_size = 100  # 批次大小
saver = tf.train.Saver()  # 模型保存、加载对象
model_path = "model/mnist/mnist_model.ckpt"  # 模型前缀

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())  # 初始化
    batches = int(mnist.train.num_examples / batch_size)  # 训练批次

    for epoch in range(200):  # 外层循环控制训练轮次
        avg_cost = 0.0  # 损失值临时变量

        for i in range(batches):  # 内层循环控制训练批次
            # 取一个批次样本 xs-图像数据 ys-标签
            xs, ys = mnist.train.next_batch(batch_size)
            params = {x: xs, y: ys}  # 参数字典(给占位符传参)

            # 执行梯度下降优化操作、损失值操作
            o, c = sess.run([optimizer, cost], feed_dict=params)
            avg_cost += (c / batches)  # 计算损失函数平均值
        print("ecoch:%d, cost:%f" % (epoch, avg_cost))
    print("训练结束.")

    # 模型评估(使用测试集预测,计算准确率)
    ## 取真实值、预测值最大值的索引进行比较,返回布尔类型张量
    correct_pred = tf.equal(tf.argmax(pred_y, 1),
                            tf.argmax(y, 1))
    ## 布尔类型转浮点数,再累加除以元素个数
    accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
    params = {x: mnist.test.images, y: mnist.test.labels}  # 参数字典
    acc = sess.run(accuracy, feed_dict=params)  # 执行准确率计算
    print("Test Accuracy:", acc)

    save_path = saver.save(sess, model_path)  # 保存模型
    print("保存模型成功:", save_path)

# 第五步:模型加载、预测
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    saver.restore(sess, model_path)  # 加载模型

    xs, ys = mnist.test.next_batch(2)  # 读取两个测试样本
    output = tf.argmax(pred_y, 1)  # 返回最大概率索引(最终识别结果)
    params = {x: xs, y: ys}
    output_val, predv = sess.run([output, pred_y],
                                 feed_dict=params)
    print("预测结论:", output_val, "\n")
    print("实际结果:", ys, "\n")  # 实际结果是标签
    print("预测概率:", predv, "\n")

    # 显示图像
    im = xs[0]  # 第1个图像
    im = im.reshape(28, 28)  # 还原成二维
    pylab.imshow(im)  # 设置要显示的图像
    pylab.show()  # 显示

    im = xs[1]  # 第2个图像
    im = im.reshape(28, 28)  # 还原成二维
    pylab.imshow(im)  # 设置要显示的图像
    pylab.show()  # 显示

# 02_fashion_mnist_demo.py
# 利用CNN实现服饰识别
import tensorflow as tf
from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets


class FashionMnist():
    flt_num1 = 12  # 第一个卷积层卷积核数量
    flt_num2 = 24  # 第二个卷积层卷积核数量
    con_neurons = 512  # 第一个全连接层神经元数量

    def __init__(self, path):
        """
        构造方法
        :param path: 数据集路径
        """
        self.sess = tf.Session()  # Session对象
        self.data = read_data_sets(path,
                                   one_hot=True)  # 数据读取对象

    def init_weight(self, shape):
        """
        根据指定形状,初始化权重
        :param shape: 形状
        :return: 经过初始化后的权重变量
        """
        # 截尾正态分布(正态分布的变种)
        inital = tf.truncated_normal(shape, stddev=0.1)
        return tf.Variable(inital)

    def init_bias(self, shape):
        """
        根据指定形状,初始化偏置
        :param shape: 形状
        :return: 经过初始化后的偏置变量
        """
        inital = tf.constant(1.0, shape=shape)
        return tf.Variable(inital)

    def conv2d(self, x, w):
        """
        二维卷积
        :param x: 输入
        :param w: 卷积核
        :return: 卷积运算结果
        """
        return tf.nn.conv2d(x,  # 输入
                            w,  # 卷积核
                            strides=[1, 1, 1, 1],  # 各个维度上的步幅
                            padding="SAME")  # 输入输出矩阵一样大

    def max_pool_2x2(self, x):
        """
        池化
        :param x: 输入
        :return: 池化计算结果
        """
        return tf.nn.max_pool(x,  # 输入
                              ksize=[1, 2, 2, 1],  # 池化区域
                              strides=[1, 2, 2, 1],  # 步长
                              padding="SAME")

    def create_conv_pool(self, input,
                         input_features, out_features):
        """
        卷积、激活、池化层
        :param input: 输入
        :param input_features: 输入通道数量
        :param out_features: 输出通道数量
        :return: 卷积、激活、池化层计算结果
        """
        # 创建卷积核,shape表示 [h, w, in_channel, out_channel]
        filter = self.init_weight(
            [5, 5, input_features, out_features])
        # 定义偏置
        b_conv = self.init_bias([out_features])  # 数量和输出通道数一致

        # 卷积、激活运算
        h_conv = tf.nn.relu(self.conv2d(input, filter) + b_conv)
        # 池化
        h_pool = self.max_pool_2x2(h_conv)
        return h_pool

    def create_fc(self, h_pool_flat, input_features, con_neurons):
        """
        全连接层
        :param h_pool_flat: 输入数据(经过拉伸的一维张量)
        :param input_features: 输入特征值数量
        :param con_neurons: 神经元数量(即输出值的数量)
        :return: 全连接层计算结果
        """
        w_fc = self.init_weight([input_features, con_neurons])
        b_fc = self.init_bias([con_neurons])  # 偏置
        # 全连接层计算
        h_fc1 = tf.nn.relu(tf.matmul(h_pool_flat, w_fc) + b_fc)

        return h_fc1

    def build(self):
        """
        组建CNN
        :return: 模型预测结果
        """
        # 样本数据
        self.x = tf.placeholder(tf.float32, [None, 784])  # 图像
        x_image = tf.reshape(self.x, [-1, 28, 28, 1])  # 变维
        self.y = tf.placeholder(tf.float32, [None, 10])  # 标签

        # 第一层卷积/池化
        h_pool1 = self.create_conv_pool(
            x_image,  # 输入
            1,  # 输入通道数
            self.flt_num1)  # 输出通道数
        # 第二层卷积/池化
        h_pool2 = self.create_conv_pool(
            h_pool1, # 输入(上一层的输出作为本层输入)
            self.flt_num1, # 输入通道数(上一层输出通道数)
            self.flt_num2) # 输出通道数(即本层卷积核数量)
        # 全连接层
        h_pool2_fetures = 7 * 7 * self.flt_num2
        h_pool2_flat = tf.reshape(h_pool2, [-1, h_pool2_fetures])
        h_fc = self.create_fc(h_pool2_flat, # 输入(经过变维的张量)
                              h_pool2_fetures, # 输入特征数量
                              self.con_neurons)# 输出值数量
        # dropout(通过随机丢弃一定比例神经元,缓解过拟合)
        self.keep_prob = tf.placeholder("float") # 保持率
        h_drop = tf.nn.dropout(h_fc, # 输入(上一层的输出)
                               self.keep_prob)# 保持率
        # 全连接层
        w_fc = self.init_weight([self.con_neurons, 10])
        b_fc = self.init_bias([10])
        y_conv = tf.matmul(h_drop, w_fc) + b_fc # 全连接计算

        # 定义损失函数
        loss_func = tf.nn.softmax_cross_entropy_with_logits(
            labels=self.y, # 真实值
            logits=y_conv) # 预测值
        cross_entropy = tf.reduce_mean(loss_func)
        # 优化器
        optimizer = tf.train.AdamOptimizer(0.001)
        self.train_step = optimizer.minimize(cross_entropy)

        # 准确率
        correct_pred = tf.equal(tf.argmax(y_conv, 1),
                                tf.argmax(self.y, 1))
        self.accuracy = tf.reduce_mean(
            tf.cast(correct_pred, tf.float32)) # 计算准确率

    def train(self): # 训练
        self.sess.run(tf.global_variables_initializer())

        batch_size = 100 # 批次大小
        batches = int(self.data.train.num_examples / batch_size)

        for i in range(20): # 外层循环控制训练轮次
            for j in range(batches): # 内层循环控制训练批次
                # 读取一个批次样本
                xs, ys = self.data.train.next_batch(batch_size)
                # 构建参数字典
                params = {self.x: xs, # 图像
                          self.y: ys, # 标签
                          self.keep_prob: 0.5} # 保持率

                t, acc = self.sess.run(
                    [self.train_step, self.accuracy],#执行的操作
                    feed_dict=params)# 喂入的参数

                if j % 100 == 0:
                    print("i:%d, j:%d, acc:%f" % (i, j, acc))
        print("训练结束.")

    def eval(self, x, y, keep_prob): # 模型评价
        params = {self.x:x, self.y:y, self.keep_prob:keep_prob}
        test_acc = self.sess.run(self.accuracy, params) # 准确率
        print("Test Accuracy:", test_acc)
        return test_acc

    def close(self): # 关闭会话
        self.sess.close()

if __name__ == "__main__":
    mnist = FashionMnist("FASHION_MNIST_data/") # 实例化对象
    mnist.build() # 定义CNN
    mnist.train() # 训练

    print("\n --------- Test ---------")
    xs, ys = mnist.data.test.next_batch(100) # 读取100个测试样本
    mnist.eval(xs, ys, 1.0) # 使用测试数据评估
    mnist.close()

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

dpq666dpq666

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值