溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

tensorflow入門(mén)之訓(xùn)練簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò)方法

發(fā)布時(shí)間:2020-09-08 15:47:04 來(lái)源:腳本之家 閱讀:201 作者:py小菜鳥(niǎo) 欄目:開(kāi)發(fā)技術(shù)

這幾天開(kāi)始學(xué)tensorflow,先來(lái)做一下學(xué)習(xí)記錄

一.神經(jīng)網(wǎng)絡(luò)解決問(wèn)題步驟:

1.提取問(wèn)題中實(shí)體的特征向量作為神經(jīng)網(wǎng)絡(luò)的輸入。也就是說(shuō)要對(duì)數(shù)據(jù)集進(jìn)行特征工程,然后知道每個(gè)樣本的特征維度,以此來(lái)定義輸入神經(jīng)元的個(gè)數(shù)。

2.定義神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu),并定義如何從神經(jīng)網(wǎng)絡(luò)的輸入得到輸出。也就是說(shuō)定義輸入層,隱藏層以及輸出層。

3.通過(guò)訓(xùn)練數(shù)據(jù)來(lái)調(diào)整神經(jīng)網(wǎng)絡(luò)中的參數(shù)取值,這是訓(xùn)練神經(jīng)網(wǎng)絡(luò)的過(guò)程。一般來(lái)說(shuō)要定義模型的損失函數(shù),以及參數(shù)優(yōu)化的方法,如交叉熵?fù)p失函數(shù)和梯度下降法調(diào)優(yōu)等。

4.利用訓(xùn)練好的模型預(yù)測(cè)未知的數(shù)據(jù)。也就是評(píng)估模型的好壞。

二.訓(xùn)練簡(jiǎn)單的向前傳播神經(jīng)網(wǎng)絡(luò)

一下訓(xùn)練的神經(jīng)模型是最簡(jiǎn)單的一類(lèi),而且是線性的(也就是說(shuō)沒(méi)有用激活函數(shù)去線性話),沒(méi)有反向傳播的過(guò)程,只是簡(jiǎn)單的說(shuō)明神經(jīng)網(wǎng)絡(luò)工作的流程。

import tensorflow as tf

#定義隱藏層參數(shù),每個(gè)w變量是一個(gè)tensor(可以當(dāng)成是n*m的數(shù)組,n表示上一層結(jié)點(diǎn)個(gè)數(shù),m表示本層結(jié)點(diǎn)個(gè)數(shù))表示上一層與本層的連接權(quán)重,這里先隨機(jī)定義權(quán)重
w1=tf.Variable(tf.random_normal([2,3],stddev=1))
w2=tf.Variable(tf.random_normal([3,1],stddev=1))

#定義存放輸入數(shù)據(jù)的地方,也就是x向量,這里shape為前一個(gè)傳入訓(xùn)練的樣本個(gè)數(shù),后面出入每個(gè)樣本的維度大小
x=tf.placeholder(tf.float32,shape=(None,2),name="input")
#矩陣乘法
a=tf.matmul(x,w1)
y=tf.matmul(a,w2)

with tf.Session() as sess:
  #新版本好像不能用這個(gè)函數(shù)初始化所有變量了
  init_op=tf.initialize_all_variables()
  sess.run(init_op)
  #feed_dict用于向y中的x傳入?yún)?shù),這里傳入3個(gè),則y輸出為一個(gè)3*1的tensor
  print(sess.run(y,feed_dict={x:[[0.7,0.9],[1.0,1.5],[2.1,2.3]]}))

至此,一個(gè)用x的每個(gè)維度乘以兩層權(quán)重之后輸出單個(gè)值得線性神經(jīng)網(wǎng)絡(luò)就定義好了。

三.定義損失函數(shù)以及反向傳播算法

有了上面的基礎(chǔ),我們可以定義損失函數(shù)以及反向傳播算法去擬合數(shù)據(jù)了,非線性數(shù)據(jù)我們可以定義激活函數(shù)去線性化。還有一些細(xì)節(jié)就是學(xué)習(xí)率的問(wèn)題,這次使用的是動(dòng)態(tài)學(xué)習(xí)率,首先把學(xué)習(xí)率設(shè)定為比較大的值,加速收斂,然后隨著迭代次數(shù)的增加,學(xué)習(xí)率不斷下降,防止錯(cuò)過(guò)局部最小值。還有一個(gè)問(wèn)題,就是防止過(guò)擬合。一般神經(jīng)網(wǎng)絡(luò)防止過(guò)擬合的策略有兩種,一種是正則化,一種是dropout,我們暫且不作討論后者

損失函數(shù):交叉熵

反向傳播算法:梯度下降法

激活函數(shù):relu

# -*- coding: utf-8 -*-
"""
Created on Fri Aug 18 14:02:19 2017

@author: osT
"""
import tensorflow as tf 
import numpy as np
#導(dǎo)入數(shù)據(jù),這里的數(shù)據(jù)是每一行代表一個(gè)樣本,每一行最后一列表示樣本標(biāo)簽,0-32一共33個(gè)類(lèi)
data=np.loadtxt('train_data.txt',dtype='float',delimiter=',')

#將樣本標(biāo)簽轉(zhuǎn)換成獨(dú)熱編碼
def label_change(before_label):
  label_num=len(before_label)
  change_arr=np.zeros((label_num,33))
  for i in range(label_num):
    #該樣本標(biāo)簽原本為0-32的,本人疏忽下32標(biāo)記成33
    if before_label[i]==33.0:
      change_arr[i,int(before_label[i]-1)]=1
    else:
      change_arr[i,int(before_label[i])]=1
  return change_arr

#定義神經(jīng)網(wǎng)絡(luò)的輸入輸出結(jié)點(diǎn),每個(gè)樣本為1*315維,以及輸出分類(lèi)結(jié)果
INPUT_NODE=315
OUTPUT_NODE=33

#定義兩層隱含層的神經(jīng)網(wǎng)絡(luò),一層300個(gè)結(jié)點(diǎn),一層100個(gè)結(jié)點(diǎn)
LAYER1_NODE=300
LAYER2_NODE=100

#定義學(xué)習(xí)率,學(xué)習(xí)率衰減速度,正則系數(shù),訓(xùn)練調(diào)整參數(shù)的次數(shù)以及平滑衰減率
LEARNING_RATE_BASE=0.5
LEARNING_RATE_DECAY=0.99
REGULARIZATION_RATE=0.0001
TRAINING_STEPS=2000
MOVING_AVERAGE_DECAY=0.99

#定義整個(gè)神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu),也就是向前傳播的過(guò)程,avg_class為平滑可訓(xùn)練量的類(lèi),不傳入則不使用平滑
def inference(input_tensor,avg_class,w1,b1,w2,b2,w3,b3):
  if avg_class==None:
    #第一層隱含層,輸入與權(quán)重矩陣乘后加上常數(shù)傳入激活函數(shù)作為輸出
    layer1=tf.nn.relu(tf.matmul(input_tensor,w1)+b1)
    #第二層隱含層,前一層的輸出與權(quán)重矩陣乘后加上常數(shù)作為輸出
    layer2=tf.nn.relu(tf.matmul(layer1,w2)+b2)
    #返回 第二層隱含層與權(quán)重矩陣乘加上常數(shù)作為輸出
    return tf.matmul(layer2,w3)+b3
  else:
    #avg_class.average()平滑訓(xùn)練變量,也就是每一層與上一層的權(quán)重
    layer1=tf.nn.relu(tf.matmul(input_tensor,avg_class.average(w1))+avg_class.average(b1))
    layer2=tf.nn.relu(tf.matmul(layer1,avg_class.average(w2))+avg_class.average(b2))
    return tf.matmul(layer2,avg_class.average(w3))+avg_class.average(b3)

def train(data):
  #混洗數(shù)據(jù)
  np.random.shuffle(data)
  #取錢(qián)850個(gè)樣本為訓(xùn)練樣本,后面的全是測(cè)試樣本,約250個(gè)
  data_train_x=data[:850,:315]
  data_train_y=label_change(data[:850,-1])
  data_test_x=data[850:,:315]
  data_test_y=label_change(data[850:,-1])

  #定義輸出數(shù)據(jù)的地方,None表示無(wú)規(guī)定一次輸入多少訓(xùn)練樣本,y_是樣本標(biāo)簽存放的地方
  x=tf.placeholder(tf.float32,shape=[None,INPUT_NODE],name='x-input')
  y_=tf.placeholder(tf.float32,shape=[None,OUTPUT_NODE],name='y-input')

  #依次定義每一層與上一層的權(quán)重,這里用隨機(jī)數(shù)初始化,注意shape的對(duì)應(yīng)關(guān)系
  w1=tf.Variable(tf.truncated_normal(shape=[INPUT_NODE,LAYER1_NODE],stddev=0.1))
  b1=tf.Variable(tf.constant(0.1,shape=[LAYER1_NODE]))

  w2=tf.Variable(tf.truncated_normal(shape=[LAYER1_NODE,LAYER2_NODE],stddev=0.1))
  b2=tf.Variable(tf.constant(0.1,shape=[LAYER2_NODE]))

  w3=tf.Variable(tf.truncated_normal(shape=[LAYER2_NODE,OUTPUT_NODE],stddev=0.1))
  b3=tf.Variable(tf.constant(0.1,shape=[OUTPUT_NODE]))

  #輸出向前傳播的結(jié)果
  y=inference(x,None,w1,b1,w2,b2,w3,b3)

  #每訓(xùn)練完一次就會(huì)增加的變量
  global_step=tf.Variable(0,trainable=False)

  #定義平滑變量的類(lèi),輸入為平滑衰減率和global_stop使得每訓(xùn)練完一次就會(huì)使用平滑過(guò)程
  variable_averages=tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)
  #將平滑應(yīng)用到所有可訓(xùn)練的變量,即trainable=True的變量
  variable_averages_op=variable_averages.apply(tf.trainable_variables())

  #輸出平滑后的預(yù)測(cè)值
  average_y=inference(x,variable_averages,w1,b1,w2,b2,w3,b3)

  #定義交叉熵和損失函數(shù),但為什么傳入的是label的arg_max(),就是對(duì)應(yīng)分類(lèi)的下標(biāo)呢,我們遲點(diǎn)再說(shuō)
  cross_entropy=tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y,labels=tf.arg_max(y_,1))
  #計(jì)算交叉熵的平均值,也就是本輪訓(xùn)練對(duì)所有訓(xùn)練樣本的平均值
  cross_entrip_mean=tf.reduce_mean(cross_entropy)

  #定義正則化權(quán)重,并將其加上交叉熵作為損失函數(shù)
  regularizer=tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)
  regularization=regularizer(w1)+regularizer(w2)+regularizer(w3)
  loss=cross_entrip_mean+regularization

  #定義動(dòng)態(tài)學(xué)習(xí)率,隨著訓(xùn)練的步驟增加不斷遞減
  learning_rate=tf.train.exponential_decay(LEARNING_RATE_BASE,global_step,900,LEARNING_RATE_DECAY)
  #定義向后傳播的算法,梯度下降發(fā),注意后面的minimize要傳入global_step
  train_step=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step)
  #管理需要更新的變量,傳入的參數(shù)是包含需要訓(xùn)練的變量的過(guò)程
  train_op=tf.group(train_step,variable_averages_op)

  #正確率預(yù)測(cè)
  correct_prediction=tf.equal(tf.arg_max(average_y,1),tf.arg_max(y_,1))
  accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

  with tf.Session() as sess:
    #初始所有變量
    tf.global_variables_initializer().run()
    #訓(xùn)練集輸入字典
    validate_feed={x:data_train_x,y_:data_train_y}
    #測(cè)試集輸入字典
    test_feed={x:data_test_x,y_:data_test_y}

    for i in range(TRAINING_STEPS):
      if i%1000==0:
        validate_acc=sess.run(accuracy,feed_dict=validate_feed)
        print("After %d training step(s),validation accuracy using average model is %g"%(i,validate_acc))
      #每一輪通過(guò)同一訓(xùn)練集訓(xùn)練,由于樣本太少,沒(méi)辦法了
      sess.run(train_op,feed_dict=validate_feed)
    #用測(cè)試集查看模型的準(zhǔn)確率
    test_acc=sess.run(accuracy,feed_dict=test_feed)
    print("After %d training step(s),test accuracy using average model is %g"%(TRAINING_STEPS,test_acc))
train(data)

然后我們來(lái)看一下為什么計(jì)算交叉熵時(shí)要傳入樣本的下標(biāo):

首先我們知道,輸出結(jié)點(diǎn)有33個(gè),通過(guò)與前面的權(quán)重相乘后,則每個(gè)結(jié)點(diǎn)都會(huì)有一個(gè)輸出,每個(gè)輸出我們暫且認(rèn)為是對(duì)應(yīng)每個(gè)類(lèi)的概率,該值越大,我們就越認(rèn)為該樣本為對(duì)應(yīng)的類(lèi)。logits參數(shù)是神經(jīng)網(wǎng)絡(luò)的直接輸出,也就是未經(jīng)softmax函數(shù)處理的輸出,labels傳入的是單個(gè)值,也就是分類(lèi)對(duì)應(yīng)的下標(biāo),這是由于我們使用的計(jì)算交叉熵的函數(shù) tf.nn.sparse_softmax_cross_entropy_with_logits()有關(guān)。這個(gè)函數(shù)對(duì)于在只有一個(gè)正確分類(lèi)的模型計(jì)算起到加速作用,而這個(gè)labels的輸入就是“這一個(gè)正確的分類(lèi)”,對(duì)應(yīng)到輸出的結(jié)點(diǎn),就是其下標(biāo)了。我們還有一個(gè)沒(méi)有加速的交叉熵函數(shù):tf.nn.softmax_cross_entropy_with_logis(logis=,labels=)這個(gè)時(shí)候我們就應(yīng)該傳入本身的labels標(biāo)簽了。

最后,我們來(lái)總結(jié)一下提高模型準(zhǔn)確率的方法:

1.使用激活函數(shù)。也就是去線性化,這步幾乎是必須的。
2.增加隱含層。就本例而言,單隱含層300個(gè)結(jié)點(diǎn),準(zhǔn)確率在89%左右;單隱含層400個(gè)結(jié)點(diǎn),準(zhǔn)確率在93%左右;而雙隱含層300結(jié)點(diǎn)和100結(jié)點(diǎn),準(zhǔn)確率在94%左右。但增加隱含層意味著增加訓(xùn)練時(shí)間。
3.使用動(dòng)態(tài)學(xué)習(xí)率。這不但可以加快訓(xùn)練的速度,還可以增加神經(jīng)網(wǎng)絡(luò)收斂到較低的極小值處的概率,從而增加準(zhǔn)確率。
4.使用平滑模型。主要可以增加模型的健壯性,使其泛化能力更強(qiáng)。
5.加入正則化或者使用dropout防止過(guò)擬合。

附上訓(xùn)練集

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI