機器學習|兩個隱藏層的Softmax分類器

Tensorflow實現兩個隱藏層的Softmax分類器

Softmax分類器介紹

之前用Tensorflow實現Logistic迴歸模型的博客裏面講解了Logistic,最後順便提了一下Softmax模型,並給出了一個實例。Softmax是用於分類過程,用來實現多分類的,簡單來說,它把一些輸出的神經元映射到(0-1)之間的實數,並且歸一化保證和爲1,從而使得多分類的概率之和也剛好爲1。不同於Logistic迴歸模型,Logistic迴歸是用於二分類,輸出結果非0即1,而Softmax是用於多分類問題,輸出結果屬於哪個類是以概率的形式給出來的。比如mnist數據集上面的一個例子,輸入數據是8,用softmax迴歸模型判斷可能會給出屬於不同數字的概率:
在這裏插入圖片描述
這是一種較爲通俗的解釋,當然我們也可以直接從這個名字入手去解釋,Softmax可以分爲soft和max,max也就是最大值,假設有兩個變量a,b。如果a>b,則max爲a,反之爲b。那麼在分類問題裏面,如果只有max,輸出的分類結果只有a或者b,是個非黑即白的結果。但是在現實情況下,我們希望輸出的是取到某個分類的概率,或者說,我們希望分值大的那一項被經常取到,而分值較小的那一項也有一定的概率偶爾被取到,所以我們就應用到了soft的概念,即最後的輸出是每個分類被取到的概率。

Softmax函數

求特徵:ii代表第i類,jj代表一張圖片的第jj個像素。WW是權重,bb是偏置。在網絡的最後一層是一個線性輸出層:
zj=jwj,ixi+bj z_{j}=\sum_{j}w_{j,i}x_{i}+b_{j}
求softmax:接下來對所有特徵計算softmax,首先是計算一個指數expexp函數,然後在對其進行標準化,保證所有類別輸出的概率和爲1.其中判定爲第ii類的概率可以由下面公式得到:
softmax(x)j=exp(zj)jexp(xj) softmax(x)_{j}=\frac{exp(z_{j})}{\sum_{j}exp(x_{j})}

Tensorflow實現兩個隱藏層的Softmax分類器

下面用Tensorflow實現下圖所示的兩個隱藏層的softmax網絡,其中輸入xx先經過隱藏層1(hidden1)和隱藏層2(hidden2),然後在經過線性輸出層得到預測輸出logits,最後把logits變成概率分佈,
在這裏插入圖片描述
如果用的是mnist數據集,最後一層就有十個神經單元,最終輸出十個概率分佈:
在這裏插入圖片描述
最終得到的計算圖如下:
在這裏插入圖片描述
最後給出tensorflow實現代碼。


import os.path
import tensorflow as tf
import os
import sys
from six.moves import xrange
import time
import argparse

from tensorflow.examples.tutorials.mnist import input_data
import TwoLayer_softmax

os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
#定義模型的超參數
FLAGS=None

def fill_feed_dict(data_set,image_pl,label_pl):
    image_feed,label_feed=data_set.next_batch(FLAGS.batch_size,FLAGS.fake_data)
    feed_dict={image_pl:image_feed,label_pl:label_feed}
    return feed_dict

def do_eval(sess,eval_correct,image_placeholder,label_placeholder,data_set):
    #運行一個回合的評估過程
    true_count=0
    steps_per_epoch=data_set.num_examples//FLAGS.batch_size  #每個回合的執行步數
    num_examples=steps_per_epoch*FLAGS.batch_size    #樣本總量
    #累加每個批次樣本中預測正確的樣本數量
    for step in xrange(steps_per_epoch):
        feed_dict=fill_feed_dict(data_set,image_placeholder,label_placeholder)
        true_count+=sess.run(eval_correct,feed_dict=feed_dict)
    #所有批次上面的精確度
    precision=float(true_count)/num_examples
    print('Num examples: %d Num correct: %d Precision @ 1:%0.04f' % (num_examples,true_count,precision))





def run_training():
    data_sets=input_data.read_data_sets(FLAGS.input_data_dir,FLAGS.fake_data)
    with tf.Graph().as_default():
        image_palceholder, labels_placeholder =TwoLayer_softmax.placeholder_inputs(FLAGS.batch_size)

        logits=TwoLayer_softmax.inference(image_palceholder,FLAGS.hidden1,FLAGS.hidden2)

        loss=TwoLayer_softmax.loss(logits,labels_placeholder)

        trainOp=TwoLayer_softmax.training(loss,FLAGS.learning_rate)

        eval_correct=TwoLayer_softmax.evaluate(logits,labels_placeholder)

        merge_summary = tf.summary.merge_all()

        init=tf.global_variables_initializer()

        saver=tf.train.Saver()

        with tf.Session() as sess:
            summary_writer=tf.summary.FileWriter(FLAGS.log_dir,graph=tf.get_default_graph())

            sess.run(init)

            for step in xrange(FLAGS.max_step):
                start_time=time.time()

                feed_dict=fill_feed_dict(data_sets.train,image_palceholder,labels_placeholder)

                _,loss_value=sess.run([trainOp,loss],feed_dict=feed_dict)

                duration=time.time()-start_time

                if step%100==0:
                    print('Step %d: loss = %.2f(%.3f sec)'%(step,loss_value,duration))
                    summaries_str=sess.run(merge_summary,feed_dict=feed_dict)
                    summary_writer.add_summary(summaries_str,global_step=step)
                    summary_writer.flush()

                if (step+1)%1000==0 or (step+1)==FLAGS.max_step:
                    checkpoint_file=os.path.join(FLAGS.log_dir,'model.ckpt')
                    saver.save(sess,checkpoint_file,global_step=step)

                    print('Training Data Eval:')
                    do_eval(sess,
                            eval_correct,
                            image_palceholder,
                            labels_placeholder,
                            data_sets.train
                    )

                    print('Validation Data Eval:')
                    do_eval(sess,
                            eval_correct,
                            image_palceholder,
                            labels_placeholder,
                            data_sets.validation
                    )

                    print('Test Data Eval:')
                    do_eval(sess,
                            eval_correct,
                            image_palceholder,
                            labels_placeholder,
                            data_sets.test
                    )


def main(_):
    if tf.gfile.Exists(FLAGS.log_dir):
        tf.gfile.DeleteRecursively(FLAGS.log_dir)
    tf.gfile.MakeDirs(FLAGS.log_dir)
    run_training()

if __name__=='__main__':
    parser=argparse.ArgumentParser()
    parser.add_argument(
        '--learning_rate',
        type=float,
        default=0.5,
        help='initial learning rate'
    )
    parser.add_argument(
        '--max_step',
        type=int,
        default=2000,
        help='Number of steps to run trainer.'
    )
    parser.add_argument(
        '--hidden1',
        type=int,
        default=128,
        help='Number of units in hidden layer 1'
    )
    parser.add_argument(
        '--hidden2',
        type=int,
        default=32,
        help='Number of units in hidden layer 2'
    )
    parser.add_argument(
        '--batch_size',
        type=int,
        default=100,
        help='Batch size.Must divide evenly into the dataset size.'
    )
    parser.add_argument(
        '--input_data_dir',
        type=str,
        default='mnist_data/',
        help='Directory to put the input data'
    )
    parser.add_argument(
        '--log_dir',
        type=str,
        default='LOG_Twohidden_fullconnect',
        help='Directory to input the log data'
    )
    parser.add_argument(
        '--fake_data',
        default=False,
        help='If true,uses fake data for unit testing',
        action='store_true'
    )

    FLAGS,unparsed = parser.parse_known_args()
    tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)

#文件名字爲TwoLayer_softmax.py
import tensorflow as tf
import os
import math
from tensorflow.examples.tutorials.mnist import input_data
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'


#mnist=input_data.read_data_sets('mnist_data/',one_hot=True)
IMAGE_SIZE=28
IMAGE_PIXELS=IMAGE_SIZE*IMAGE_SIZE
#batch_size=50
#hidden1_units=20
#hidden2_units=15
#learning_rate=0.01

NUM_Class=10

def placeholder_inputs(batch_size):
    image_palceholder = tf.placeholder(tf.float32, shape=(batch_size, IMAGE_PIXELS))
    labels_placeholder = tf.placeholder(tf.int32, shape=(batch_size))
    return image_palceholder,labels_placeholder

def inference(image,hidden1_units,hidden2_units):
    with tf.name_scope('hidden1'):
        w=tf.Variable(tf.random.truncated_normal([IMAGE_PIXELS,hidden1_units],   #mean-2*stddev~mean+2*stddev
                                                 stddev=1.0/math.sqrt(float(IMAGE_PIXELS))),name='Weight')
    # 以weights矩陣的行數規範化標準差,就是讓weights矩陣的每一列都服從0均值截斷正態分佈,這樣不會給輸入信號加入人爲的偏置

        b=tf.Variable(tf.zeros([hidden1_units]),name='bias')
        hidden1=tf.nn.relu(tf.add(tf.matmul(image,w),b))
    with tf.name_scope('hidden2'):
        w=tf.Variable(tf.random.truncated_normal([hidden1_units,hidden2_units],
                                                 stddev=1.0/math.sqrt(float(hidden1_units))),name='weight')
        b=tf.Variable(tf.zeros([hidden2_units]),name='bias')
        hidden2=tf.nn.relu(tf.add(tf.matmul(hidden1,w),b))

    with tf.name_scope('softmax_linear'):
        w=tf.Variable(tf.random.truncated_normal([hidden2_units,NUM_Class],
                                                 stddev=1.0/math.sqrt(float(hidden2_units))),name='weight')
        b=tf.Variable(tf.zeros([NUM_Class]),name='bias')
        logits=tf.add(tf.matmul(hidden2,w),b)
        return logits

def loss(logits,labels):
    labels=tf.to_int64(labels)
    cross_entrypy=tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels,logits=logits,name='xentrypy')
    #把logist轉化爲softmax上面的概率分佈
    return tf.reduce_mean(cross_entrypy,name='xentrypy_mean')

def training(loss,learning_rate):
    with tf.name_scope('scalar_summaries'):
        tf.summary.scalar('learning_rate',learning_rate)
        tf.summary.scalar('loss',loss)
    Optimizer=tf.train.GradientDescentOptimizer(learning_rate)
    global_step=tf.Variable(0,name='global_step',trainable=False)
    trainOp=Optimizer.minimize(loss,global_step)
    return trainOp

def evaluate(logits,labels):
    correct=tf.nn.in_top_k(predictions=logits,targets=labels,k=1)
    return tf.reduce_sum(input_tensor=tf.cast(correct,tf.int32))

# image_palceholder,labels_placeholder=placeholder_inputs(batch_size)
# logits=inference(image_palceholder,hidden1_units,hidden2_units)
# batch_loss=loss(logits,labels=labels_placeholder)
# train_batch=training(batch_loss,learning_rate=learning_rate)
# correct_counts=evaluate(logits=logits,labels=labels_placeholder)

# Init=tf.global_variables_initializer()
#
# print('計算圖已經寫入!在Tensorboard中查看!')
# writer=tf.summary.FileWriter(logdir='LOG_TwoLayer_Softmax',graph=tf.get_default_graph())
# writer.flush()


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章