Tensorflow之softmax应用实例

语言:python3.6

框架:   tensorflow

数据集:mnist数据集(图片格式)

1、准备数据集

下载地址:http://yann.lecun.com/exdb/mnist/

用以下的代码将minist数据集转化为图片(也可以通过from tensorflow.examples.tutorials.mnist import input_data获得二进格式的数据)

"""
将MNIST数据集由二进制文件转为图片形式,保存于指定文件夹下
"""
import os
import struct
import numpy as np
import matplotlib.pyplot as plt

# 读MNIST数据集的图片数据
def mnist_load_img(img_path):
    with open(img_path, "rb") as fp:
        # >是以大端模式读取,i是整型模式,读取前四位的标志位,
        # unpack()函数:是将4个字节联合后再解析成一个数,(读取后指针自动后移)
        msb = struct.unpack('>i', fp.read(4))[0]
        # 标志位为2051,后存图像数据;标志位为2049,后存图像标签
        if msb == 2051:
            # 读取样本个数60000,存入cnt
            cnt = struct.unpack('>i', fp.read(4))[0]
            # rows:行数28;cols:列数28
            rows = struct.unpack('>i', fp.read(4))[0]
            cols = struct.unpack('>i', fp.read(4))[0]
            imgs = np.empty((cnt, rows, cols), dtype="int")
            for i in range(0, cnt):
                for j in range(0, rows):
                    for k in range(0, cols):
                        # 16进制转10进制
                        pxl = int(hex(fp.read(1)[0]), 16)
                        imgs[i][j][k] = pxl
            return imgs
        else:
            return np.empty(1)

# 读MNIST数据集的图片标签
def mnist_load_label(label_path):
    with open(label_path, "rb") as fp:
        msb = struct.unpack('>i', fp.read(4))[0];
        if msb == 2049:
            cnt = struct.unpack('>i', fp.read(4))[0];
            labels = np.empty(cnt, dtype="int");
            for i in range(0, cnt):
                label = int(hex(fp.read(1)[0]), 16);
                labels[i] = label;
            return labels;
        else:
            return np.empty(1);

# 分割训练、测试集的图片数据与图片标签
def mnist_load_data(train_img_path, train_label_path, test_img_path, test_label_path):
    x_train = mnist_load_img(train_img_path);
    y_train = mnist_load_label(train_label_path);
    x_test = mnist_load_img(test_img_path);
    y_test = mnist_load_label(test_label_path);
    return (x_train, y_train), (x_test, y_test);

# 输出打印图片
def mnist_plot_img(img):
    (rows, cols) = img.shape;
    plt.figure();
    plt.gray();
    plt.imshow(img);
    plt.show();

# 按指定位置保存图片
def mnist_save_img(img, path, name):
    if not os.path.exists(path):
        os.mkdir(path)
    (rows, cols) = img.shape
    fig = plt.figure()
    plt.gray()
    plt.imshow(img)
    # 在既定路径里保存图片
    fig.savefig(path + name)



# [start]
x_train = mnist_load_img("train-images.idx3-ubyte")
y_train = mnist_load_label("train-labels.idx1-ubyte")

# 将打印出的MNIST数据集中所有的图片存入一个data文件夹下
# for i in range(0, 10):
#     path = "../CNN+Kreas框架+MNIST/data/data_a/"
#     name = str(i) + ".png"
#     mnist_save_img(x_train[i], path, name)

# 按图片标签的不同,打印MNIST数据集的图片存入不同文件夹下
for i in range(0, len(x_train)):
    path = "./data/" + str(y_train[i]) +"/"
    name = str(i)+".png"
    mnist_save_img(x_train[i], path, name)



#mnist_plot_img(x_train[0, :, :])
"""
x_test = mnist_load_img("t10k-images.idx3-ubyte")
y_test = mnist_load_label("t10k-labels.idx1-ubyte")
"""

代码转自(https://blog.csdn.net/zzZ_CMing/article/details/81063977

就会在所指定的目录下发现0~9文件夹,里面存放图片形式的minist数据集,接下来制作训练集(也可以用上面代码中的mnist_load_data方法)

2、制作训练集

将图片和相应标签对应起来,用以下代码实现。

class Dataset(object):
    def __init__(self,file_path,batch_size,capacity):
        self.file_path=file_path#路径文件
        self.batch_size=batch_size#batch_size
        self.capacity=capacity#队列容量
        self.image_size=28



    def num_batch(self):
        image, label = self.get_files(self.file_path)
        return len(label)//self.batch_size#一批样本中的batch个数


    def get_batch(self):
        image, label = self.get_files(self.file_path)
        batch_image, batch_label=self.get_batches(image,label,self.image_size,self.image_size,self.batch_size,self.capacity)
        return batch_image,batch_label


    def get_files(self,file_path):
        class_train = []
        label_train = []
        for train_class in os.listdir(file_path):
            for pic_name in os.listdir(file_path + train_class):
                class_train.append(file_path + train_class + '/' + pic_name)
                label_train.append(train_class)
        temp = np.array([class_train, label_train])
        temp = temp.transpose()
        np.random.shuffle(temp)

        image_list = list(temp[:, 0])
        label_list = list(temp[:, 1])
        # class is 1 2 3 4 5
        label_list = [int(i) for i in label_list]

        return image_list, label_list

    def get_batches(self,image, label, resize_w, resize_h, batch_size, capacity):
        image = tf.cast(image, tf.string)
        label = tf.cast(label, tf.int64)
        queue = tf.train.slice_input_producer([image, label])
        label = queue[1]
        image_temp = tf.read_file(queue[0])
        image = tf.image.decode_jpeg(image_temp, channels=1)

        # resize image
        # image = tf.image.resize_image_with_crop_or_pad(image, resize_w, resize_h)
        image = tf.image.resize_images(image, [resize_w, resize_h], method=0)

        image = tf.image.per_image_standardization(image)

        image_batch, label_batch = tf.train.batch([image, label], batch_size=batch_size,
                                                  num_threads=64,
                                                  capacity=capacity)
        # 1:一个batch batch_size:总共划分的batch数,784,展开为1列
        image_batch = tf.reshape(image_batch, [batch_size, resize_w * resize_w])
        images_batch = tf.cast(image_batch, tf.float32)


        labels_onehot_batch = tf.one_hot(label_batch, depth=10, on_value=1, axis=1)

        labels_batch = tf.reshape(labels_onehot_batch, [batch_size, 10])

        return images_batch, labels_batch

如果分类的类别数不为10时需要修改

label_list = tf.one_hot(label_list, depth=10, on_value=1, axis=1)中的depth(输出通道)和
labels_batch = tf.reshape(label_batch, [batch_size, 10])中的10(输出通道)

3、设计网络

    with tf.name_scope('Input'):
        X = tf.placeholder(dtype=tf.float32, shape=[None, 784], name='X_placeholder')
        Y = tf.placeholder(dtype=tf.int32, shape=[None, 10], name='Y_placeholder')

    # 2、前向网络设计
    with tf.name_scope('Inference'):
        # batch:20 输入:784,通道:1,输出:10
        W = tf.Variable(initial_value=tf.random_normal(shape=[784, 10], stddev=0.01), name='Weights')
        b = tf.Variable(initial_value=tf.zeros(shape=[10]), name='bias')
        print(W)
        logits = tf.matmul(X, W) + b
        Y_pred = tf.nn.softmax(logits=logits)
    # 3、损失函数设计
    with tf.name_scope('Loss'):
        # 求交叉熵损失
        cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=Y, logits=logits, name='cross_entropy')
        # cross_entropy=tf.nn.sparse_softmax_cross_entropy_with_logits(labels=Y, logits=logits, name='cross_entropy')
        # 求平均
        loss = tf.reduce_mean(cross_entropy, name='loss')

    # 4、参数学习算法设计
    with tf.name_scope('Optimization'):
        learn_rate=0.001
        optimizer = tf.train.GradientDescentOptimizer(learn_rate).minimize(loss)

    # 5、评估节点设计
    with tf.name_scope('Evaluate'):
        # 返回验证集/测试集预测正确或错误的布尔值
        correct_prediction = tf.equal(tf.argmax(Y_pred, 1), tf.argmax(Y, 1))
        # 将布尔值转换为浮点数后,求平均准确率
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        

用一个全连接网络+softmax网络实现简单分类这里将minist的单张图片展开为[1,28*28],目的是将图片的每个像素当作其特征放入全连接网络,提取浅层特征,损失函数用交叉熵损失函数(常用于分类网络)

至此主要的工作都以做完了,加下来就是训练了,我把全部训练代码放在这里。

def main(argv=None):
    # 0、准备训练/验证/测试数据集
    log_dir='./'
    batch_size=50
    batch_image, batch_label=Dataset(data_path,50,100).get_batch()

    batch_num = Dataset(data_path,50,100).num_batch()


    # 1、数据输入设计:使用 placeholder 将数据送入网络,None 表示张量的第一个维度可以是任意长度的
    with tf.name_scope('Input'):
        X = tf.placeholder(dtype=tf.float32, shape=[None, 784], name='X_placeholder')
        Y = tf.placeholder(dtype=tf.int32, shape=[None, 10], name='Y_placeholder')

    # 2、前向网络设计
    with tf.name_scope('Inference'):
        # batch:20 输入:784,通道:1,输出:10
        W = tf.Variable(initial_value=tf.random_normal(shape=[784, 10], stddev=0.01), name='Weights')
        b = tf.Variable(initial_value=tf.zeros(shape=[10]), name='bias')
        print(W)
        logits = tf.matmul(X, W) + b
        Y_pred = tf.nn.softmax(logits=logits)
    # 3、损失函数设计
    with tf.name_scope('Loss'):
        # 求交叉熵损失
        cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=Y, logits=logits, name='cross_entropy')
        # cross_entropy=tf.nn.sparse_softmax_cross_entropy_with_logits(labels=Y, logits=logits, name='cross_entropy')
        # 求平均
        loss = tf.reduce_mean(cross_entropy, name='loss')

    # 4、参数学习算法设计
    with tf.name_scope('Optimization'):
        learn_rate=0.001
        optimizer = tf.train.GradientDescentOptimizer(learn_rate).minimize(loss)

    # 5、评估节点设计
    with tf.name_scope('Evaluate'):
        # 返回验证集/测试集预测正确或错误的布尔值
        correct_prediction = tf.equal(tf.argmax(Y_pred, 1), tf.argmax(Y, 1))
        # 将布尔值转换为浮点数后,求平均准确率
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        # correct_prediction=tf.nn.in_top_k(Y_pred, Y, 1)

    print('~~~~~~~~~~~开始执行计算图~~~~~~~~~~~~~~')

    saver = tf.train.Saver(tf.global_variables(), max_to_keep=10)
    with tf.Session() as sess:
        counter = 0
        summary_writer = tf.summary.FileWriter(logdir=log_dir, graph=sess.graph)
        # 初始化所有变量
        sess.run(tf.global_variables_initializer())
        train_epoch_loss = []
        test_epoch_loss = []
        test_val_acc = []

        coord = tf.train.Coordinator()
        threads = tf.train.start_queue_runners(sess=sess, coord=coord)
        try:
            while not coord.should_stop():
                counter += 1
                epoch_num = batch_num
                # 训练
                while epoch_num >= 0:
                    epoch_num -= 1
                    image_batch_v, label_batch_v = sess.run([batch_image, batch_label])

                    _, loss_batch, = sess.run([optimizer, loss], feed_dict={X: image_batch_v, Y: label_batch_v})
                    train_epoch_loss.append(loss_batch)

                # 验证
                while epoch_num <= batch_num:
                    epoch_num += 1
                    image_batch_v, label_batch_v = sess.run([batch_image, batch_label])
                    test_loss, acc = sess.run([loss, accuracy], feed_dict={X: image_batch_v, Y: label_batch_v})

                    test_epoch_loss.append(test_loss)
                    test_val_acc.append(acc)

                mean_train_loss = round(np.mean(np.array(train_epoch_loss)), 3)
                mean_test_loss = round(np.mean(np.array(test_epoch_loss)), 3)
                mean_val_acc = round(np.mean(np.array(test_val_acc)), 3)

                print('{} times val_acc is {}, train_loss: {},test_loss:{}'.format(counter, mean_val_acc, mean_train_loss,
                                                                                 mean_test_loss))

                if counter % 300 == 0:

                    base_dir = './checkpoint'
                    ckpt_file = base_dir + "/batch_test_loss=%.4f.ckpt" % mean_train_loss
                    print('Save ckpt file to {}'.format(ckpt_file))
                    if os.path.exists(base_dir) == False:
                        os.makedirs(base_dir)
                    saver.save(sess, ckpt_file, global_step=counter)
                if counter > 1000:
                    break


        except tf.errors.OutOfRangeError:
            print('Done!')
        finally:
            coord.request_stop()

        coord.join(threads)
        summary_writer.close()

4、验证

我们用单张图片进行验证,注意,输入的label和图片维度与训练的维度要一致。验证代码如下:

def prediect2(image):
    labels=np.array([0,1,2,3,4,5,6,7,8,9]).reshape([1,10])#单张时为[1,10],n张时为[n,10]
    trans2np=np.array(image).reshape([1,784])
    with tf.name_scope('Input'):
       x = tf.placeholder(dtype=tf.float32, shape=[None, 784], name='X_placeholder')
       y = tf.placeholder(dtype=tf.int32, shape=[None,10], name='Y_placeholder')

    # 2、前向网络设计
    with tf.name_scope('Inference'):
        # batch:20 输入:784,通道:1,输出:10
        W = tf.Variable(initial_value=tf.random_normal(shape=[784,10], stddev=0.01), name='Weights')
        b = tf.Variable(initial_value=tf.zeros(shape=[10]), name='bias')
        print(W)
        logits = tf.matmul(x, W) + b
        pred = tf.nn.softmax(logits=logits)

    saver=tf.train.Saver()

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())

        saver.restore(sess, save_path=  './checkpoint/batch_test_loss=0.5550.ckpt-300')

        correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        print('accuracy: ', accuracy.eval({x:trans2np,y:labels}))

        output = tf.argmax(pred, 1)
        outputval,pre = sess.run([output,pred], feed_dict={x: trans2np, y: labels})
        print(outputval)
        print('p:',pre)

最后可以看到答应出了类别对应的ID。

在代码中用了

tf.nn.softmax_cross_entropy_with_logits(logits, labels, name=None)求交叉损失,该方法:

除去name参数用以指定该操作的name,与方法有关的一共两个参数

第一个参数logits:就是神经网络最后一层的输出,如果有batch的话,它的大小就是[batchsize,num_classes],单样本的话,大小就是num_classes

第二个参数labels:实际的标签,shape必须和logits相同。

除了用softmax_cross_entropy_with_logits方法以外还可以用tf.nn.sparse_softmax_cross_entropy_with_logits(labels, logits, name=None)该方法用法比softmax_cross_entropy_with_logits简单,不用见label转化为one_hot编码就可以使用。见如下代码:

class Dataset(object):
    def __init__(self,file_path,batch_size,capacity):
        self.file_path=file_path#路径文件
        self.batch_size=batch_size#batch_size
        self.capacity=capacity#队列容量
        self.image_size=28



    def num_batch(self):
        image, label = self.get_files(self.file_path)
        return len(label)//self.batch_size#一批样本中的batch个数


    def get_batch(self):
        image, label = self.get_files(self.file_path)
        batch_image, batch_label=self.get_batches(image,label,self.image_size,self.image_size,self.batch_size,self.capacity)
        return batch_image,batch_label


    def get_files(self,file_path):
        class_train = []
        label_train = []
        for train_class in os.listdir(file_path):
            for pic_name in os.listdir(file_path + train_class):
                class_train.append(file_path + train_class + '/' + pic_name)
                label_train.append(train_class)
        temp = np.array([class_train, label_train])
        temp = temp.transpose()
        np.random.shuffle(temp)

        image_list = list(temp[:, 0])
        label_list = list(temp[:, 1])
        # class is 1 2 3 4 5
        label_list = [int(i) for i in label_list]

        return image_list, label_list

    def get_batches(self,image, label, resize_w, resize_h, batch_size, capacity):
        image = tf.cast(image, tf.string)
        label = tf.cast(label, tf.int64)
        queue = tf.train.slice_input_producer([image, label])
        label = queue[1]
        image_temp = tf.read_file(queue[0])
        image = tf.image.decode_jpeg(image_temp, channels=1)

        # resize image
        # image = tf.image.resize_image_with_crop_or_pad(image, resize_w, resize_h)
        image = tf.image.resize_images(image, [resize_w, resize_h], method=0)

        image = tf.image.per_image_standardization(image)

        image_batch, label_batch = tf.train.batch([image, label], batch_size=batch_size,
                                                  num_threads=64,
                                                  capacity=capacity)
        # 1:一个batch batch_size:总共划分的batch数,784,展开为1列
        image_batch = tf.reshape(image_batch, [batch_size, resize_w * resize_w])
        images_batch = tf.cast(image_batch, tf.float32)



        labels_batch = tf.reshape(label_batch, [batch_size])


        return images_batch, labels_batch

def main(argv=None):
    # 0、准备训练/验证/测试数据集
    log_dir='./'
    batch_size=50
    batch_image, batch_label=Dataset(data_path,batch_size,100).get_batch()

    batch_num = Dataset(data_path,50,100).num_batch()


    # 1、数据输入设计:使用 placeholder 将数据送入网络,None 表示张量的第一个维度可以是任意长度的
    with tf.name_scope('Input'):
        X = tf.placeholder(dtype=tf.float32, shape=[None, 784], name='X_placeholder')
        Y = tf.placeholder(dtype=tf.int32, shape=[None], name='Y_placeholder')

    # 2、前向网络设计
    with tf.name_scope('Inference'):
        # batch:20 输入:784,通道:1,输出:10
        W = tf.Variable(initial_value=tf.random_normal(shape=[784, 10], stddev=0.01), name='Weights')
        b = tf.Variable(initial_value=tf.zeros(shape=[10]), name='bias')
        print(W)
        logits = tf.matmul(X, W) + b
        Y_pred = tf.nn.softmax(logits=logits)
    # 3、损失函数设计
    with tf.name_scope('Loss'):
        # 求交叉熵损失
        # cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=Y, logits=logits, name='cross_entropy')
        cross_entropy=tf.nn.sparse_softmax_cross_entropy_with_logits(labels=Y, logits=logits, name='cross_entropy')
        # 求平均
        loss = tf.reduce_mean(cross_entropy, name='loss')

    # 4、参数学习算法设计
    with tf.name_scope('Optimization'):
        learn_rate=0.001
        optimizer = tf.train.GradientDescentOptimizer(learn_rate).minimize(loss)

    # 5、评估节点设计
    with tf.name_scope('Evaluate'):
        # 返回验证集/测试集预测正确或错误的布尔值
        # correct_prediction = tf.equal(tf.argmax(Y_pred, 1), tf.argmax(Y, 1))
        # 将布尔值转换为浮点数后,求平均准确率
        correct_prediction = tf.nn.in_top_k(Y_pred, Y, 1)
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))


    print('~~~~~~~~~~~开始执行计算图~~~~~~~~~~~~~~')

    saver = tf.train.Saver(tf.global_variables(), max_to_keep=10)
    with tf.Session() as sess:
        counter = 0
        summary_writer = tf.summary.FileWriter(logdir=log_dir, graph=sess.graph)
        # 初始化所有变量
        sess.run(tf.global_variables_initializer())
        train_epoch_loss = []
        test_epoch_loss = []
        test_val_acc = []

        coord = tf.train.Coordinator()
        threads = tf.train.start_queue_runners(sess=sess, coord=coord)
        try:
            while not coord.should_stop():
                counter += 1
                epoch_num = batch_num
                # 训练
                while epoch_num >= 0:
                    epoch_num -= 1
                    image_batch_v, label_batch_v = sess.run([batch_image, batch_label])

                    _, loss_batch, = sess.run([optimizer, loss], feed_dict={X: image_batch_v, Y: label_batch_v})
                    train_epoch_loss.append(loss_batch)

                # 验证
                while epoch_num <= batch_num:
                    epoch_num += 1
                    image_batch_v, label_batch_v = sess.run([batch_image, batch_label])
                    test_loss, acc = sess.run([loss, accuracy], feed_dict={X: image_batch_v, Y: label_batch_v})

                    test_epoch_loss.append(test_loss)
                    test_val_acc.append(acc)

                mean_train_loss = round(np.mean(np.array(train_epoch_loss)), 3)
                mean_test_loss = round(np.mean(np.array(test_epoch_loss)), 3)
                mean_val_acc = round(np.mean(np.array(test_val_acc)), 3)

                print('{} times val_acc is {}, train_loss: {},test_loss:{}'.format(counter, mean_val_acc, mean_train_loss,
                                                                                 mean_test_loss))

                if counter % 300 == 0:

                    base_dir = './checkpoint'
                    ckpt_file = base_dir + "/batch_test_loss=%.4f.ckpt" % mean_train_loss
                    print('Save ckpt file to {}'.format(ckpt_file))
                    if os.path.exists(base_dir) == False:
                        os.makedirs(base_dir)
                    saver.save(sess, ckpt_file, global_step=counter)
                if counter > 1000:
                    break


        except tf.errors.OutOfRangeError:
            print('Done!')
        finally:
            coord.request_stop()

        coord.join(threads)
        summary_writer.close()


  注意:用tf.nn.sparse_softmax_cross_entropy_with_logits方法时在Dataset中用labels_batch = tf.reshape(label_batch, [batch_size])替换以下两句:

labels_onehot_batch = tf.one_hot(label_batch, depth=10, on_value=1, axis=1)
labels_batch = tf.reshape(labels_onehot_batch, [batch_size, 10])
,同时计算accuracy时也要将tf.equal替换为:tf.nn.in_top_k。

验证代码也要做相应的改变,主要是将label改为一维数据。

labels=[0,1,2,3,4,5,6,7,8,9]
def prediect2(image):
    trans2np=np.array(image).reshape([1,784])
    with tf.name_scope('Input'):
       x = tf.placeholder(dtype=tf.float32, shape=[None, 784], name='X_placeholder')
       y = tf.placeholder(dtype=tf.int32, shape=[None], name='Y_placeholder')

    # 2、前向网络设计
    with tf.name_scope('Inference'):
        # batch:20 输入:784,通道:1,输出:10
        W = tf.Variable(initial_value=tf.random_normal(shape=[784,10], stddev=0.01), name='Weights')
        b = tf.Variable(initial_value=tf.zeros(shape=[10]), name='bias')
        print(W)
        logits = tf.matmul(x, W) + b
        pred = tf.nn.softmax(logits=logits)

    saver=tf.train.Saver()

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())

        saver.restore(sess, save_path=  './checkpoint/batch_test_loss=0.5550.ckpt-300')

        # correct_prediction = tf.nn.in_top_k(pred, y, 1)
        # accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        # 
        # 
        # 
        # 
        # print('accuracy: ', accuracy.eval({x:trans2np,y:labels}))

        output = tf.argmax(pred, 1)
        outputval,pre = sess.run([output,pred], feed_dict={x: trans2np, y: labels})
        print(outputval)
        print('p:',pre)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值