1. 程式人生 > >tensorflow入門之訓練簡單的神經網路

tensorflow入門之訓練簡單的神經網路

這幾天開始學tensorflow,先來做一下學習記錄
一.神經網路解決問題步驟:
1.提取問題中實體的特徵向量作為神經網路的輸入。也就是說要對資料集進行特徵工程,然後知道每個樣本的特徵維度,以此來定義輸入神經元的個數。
2.定義神經網路的結構,並定義如何從神經網路的輸入得到輸出。也就是說定義輸入層,隱藏層以及輸出層。
3.通過訓練資料來調整神經網路中的引數取值,這是訓練神經網路的過程。一般來說要定義模型的損失函式,以及引數優化的方法,如交叉熵損失函式和梯度下降法調優等。
4.利用訓練好的模型預測未知的資料。也就是評估模型的好壞。

二.訓練簡單的向前傳播神經網路
一下訓練的神經模型是最簡單的一類,而且是線性的(也就是說沒有用啟用函式去線性話),沒有反向傳播的過程,只是簡單的說明神經網路工作的流程。

import tensorflow as tf

#定義隱藏層引數,每個w變數是一個tensor(可以當成是n*m的陣列,n表示上一層結點個數,m表示本層結點個數)表示上一層與本層的連線權重,這裡先隨機定義權重
w1=tf.Variable(tf.random_normal([2,3],stddev=1))
w2=tf.Variable(tf.random_normal([3,1],stddev=1))

#定義存放輸入資料的地方,也就是x向量,這裡shape為前一個傳入訓練的樣本個數,後面出入每個樣本的維度大小
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: #新版本好像不能用這個函式初始化所有變量了 init_op=tf.initialize_all_variables() sess.run(init_op) #feed_dict用於向y中的x傳入引數,這裡傳入3個,則y輸出為一個3*1的tensor print(sess.run(y,feed_dict={x:[[0.7,0.9],[1.0,1.5],[2.1,2.3]]}))

至此,一個用x的每個維度乘以兩層權重之後輸出單個值得線性神經網路就定義好了。

三.定義損失函式以及反向傳播演算法
有了上面的基礎,我們可以定義損失函式以及反向傳播演算法去擬合數據了,非線性資料我們可以定義啟用函式去線性化。還有一些細節就是學習率的問題,這次使用的是動態學習率,首先把學習率設定為比較大的值,加速收斂,然後隨著迭代次數的增加,學習率不斷下降,防止錯過區域性最小值。還有一個問題,就是防止過擬合。一般神經網路防止過擬合的策略有兩種,一種是正則化,一種是dropout,我們暫且不作討論後者

損失函式:交叉熵
反向傳播演算法:梯度下降法
啟用函式:relu

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

@author: osT
"""

import tensorflow as tf 
import numpy as np

#匯入資料,這裡的資料是每一行代表一個樣本,每一行最後一列表示樣本標籤,0-32一共33個類
data=np.loadtxt('train_data.txt',dtype='float',delimiter=',')

#將樣本標籤轉換成獨熱編碼
def label_change(before_label):
    label_num=len(before_label)
    change_arr=np.zeros((label_num,33))
    for i in range(label_num):
        #該樣本標籤原本為0-32的,本人疏忽下32標記成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



#定義神經網路的輸入輸出結點,每個樣本為1*315維,以及輸出分類結果
INPUT_NODE=315
OUTPUT_NODE=33

#定義兩層隱含層的神經網路,一層300個結點,一層100個結點
LAYER1_NODE=300
LAYER2_NODE=100

#定義學習率,學習率衰減速度,正則係數,訓練調整引數的次數以及平滑衰減率
LEARNING_RATE_BASE=0.5
LEARNING_RATE_DECAY=0.99
REGULARIZATION_RATE=0.0001
TRAINING_STEPS=2000
MOVING_AVERAGE_DECAY=0.99


#定義整個神經網路的結構,也就是向前傳播的過程,avg_class為平滑可訓練量的類,不傳入則不使用平滑
def inference(input_tensor,avg_class,w1,b1,w2,b2,w3,b3):
    if avg_class==None:
        #第一層隱含層,輸入與權重矩陣乘後加上常數傳入啟用函式作為輸出
        layer1=tf.nn.relu(tf.matmul(input_tensor,w1)+b1)
        #第二層隱含層,前一層的輸出與權重矩陣乘後加上常數作為輸出
        layer2=tf.nn.relu(tf.matmul(layer1,w2)+b2)
        #返回 第二層隱含層與權重矩陣乘加上常數作為輸出
        return tf.matmul(layer2,w3)+b3
    else:
        #avg_class.average()平滑訓練變數,也就是每一層與上一層的權重
        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):
    #混洗資料
    np.random.shuffle(data)
    #取錢850個樣本為訓練樣本,後面的全是測試樣本,約250個
    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])

    #定義輸出資料的地方,None表示無規定一次輸入多少訓練樣本,y_是樣本標籤存放的地方
    x=tf.placeholder(tf.float32,shape=[None,INPUT_NODE],name='x-input')
    y_=tf.placeholder(tf.float32,shape=[None,OUTPUT_NODE],name='y-input')

    #依次定義每一層與上一層的權重,這裡用隨機數初始化,注意shape的對應關係
    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]))

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

    #每訓練完一次就會增加的變數
    global_step=tf.Variable(0,trainable=False)

    #定義平滑變數的類,輸入為平滑衰減率和global_stop使得每訓練完一次就會使用平滑過程
    variable_averages=tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)
    #將平滑應用到所有可訓練的變數,即trainable=True的變數
    variable_averages_op=variable_averages.apply(tf.trainable_variables())

    #輸出平滑後的預測值
    average_y=inference(x,variable_averages,w1,b1,w2,b2,w3,b3)

    #定義交叉熵和損失函式,但為什麼傳入的是label的arg_max(),就是對應分類的下標呢,我們遲點再說
    cross_entropy=tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y,labels=tf.arg_max(y_,1))
    #計算交叉熵的平均值,也就是本輪訓練對所有訓練樣本的平均值
    cross_entrip_mean=tf.reduce_mean(cross_entropy)

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

    #定義動態學習率,隨著訓練的步驟增加不斷遞減
    learning_rate=tf.train.exponential_decay(LEARNING_RATE_BASE,global_step,900,LEARNING_RATE_DECAY)
    #定義向後傳播的演算法,梯度下降發,注意後面的minimize要傳入global_step
    train_step=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step)
    #管理需要更新的變數,傳入的引數是包含需要訓練的變數的過程
    train_op=tf.group(train_step,variable_averages_op)

    #正確率預測
    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()
        #訓練集輸入字典
        validate_feed={x:data_train_x,y_:data_train_y}
        #測試集輸入字典
        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))
            #每一輪通過同一訓練集訓練,由於樣本太少,沒辦法了
            sess.run(train_op,feed_dict=validate_feed)
        #用測試集檢視模型的準確率
        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)

然後我們來看一下為什麼計算交叉熵時要傳入樣本的下標:
首先我們知道,輸出結點有33個,通過與前面的權重相乘後,則每個結點都會有一個輸出,每個輸出我們暫且認為是對應每個類的概率,該值越大,我們就越認為該樣本為對應的類。logits引數是神經網路的直接輸出,也就是未經softmax函式處理的輸出,labels傳入的是單個值,也就是分類對應的下標,這是由於我們使用的計算交叉熵的函式 tf.nn.sparse_softmax_cross_entropy_with_logits()有關。這個函式對於在只有一個正確分類的模型計算起到加速作用,而這個labels的輸入就是“這一個正確的分類”,對應到輸出的結點,就是其下標了。我們還有一個沒有加速的交叉熵函式:tf.nn.softmax_cross_entropy_with_logis(logis=,labels=)這個時候我們就應該傳入本身的labels標籤了。

最後,我們來總結一下提高模型準確率的方法:
1.使用啟用函式。也就是去線性化,這步幾乎是必須的。
2.增加隱含層。就本例而言,單隱含層300個結點,準確率在89%左右;單隱含層400個結點,準確率在93%左右;而雙隱含層300結點和100結點,準確率在94%左右。但增加隱含層意味著增加訓練時間。
3.使用動態學習率。這不但可以加快訓練的速度,還可以增加神經網路收斂到較低的極小值處的概率,從而增加準確率。
4.使用平滑模型。主要可以增加模型的健壯性,使其泛化能力更強。
5.加入正則化或者使用dropout防止過擬合。

附上訓練集

在下一篇文章中,我將會記錄如何儲存模型,以及取出模型使用的一些細節。

相關推薦

tensorflow入門訓練簡單神經網路

這幾天開始學tensorflow,先來做一下學習記錄 一.神經網路解決問題步驟: 1.提取問題中實體的特徵向量作為神經網路的輸入。也就是說要對資料集進行特徵工程,然後知道每個樣本的特徵維度,以此來定義輸入神經元的個數。 2.定義神經網路的結構,並定義如何從

Tensorflownn 簡單神經網路學習

最近在深入研究深度學習,關於機器學習的基本知識就略過不說了,在深度學習裡面,一些概念性的東西還是很好理解的,重點是如何利用已有的知識去構建一個合適解決實際問題的模型,然後用各種小trick去把引數調優。 試水階段,為了訓一個簡單的二分類問題,搭了一個兩層的神經

tensorflow構建兩層簡單神經網路(全連線)

中國大學Mooc 北京大學 人工智慧實踐:Tensorflow筆記(week3) #coding:utf-8 #兩層簡單神經網路(全連線) import tensorflow as tf #定義輸入和引數 #用placeholder實現輸入定義(sess.run中喂一組資料) x = tf.pl

深度學習:tensorflow入門:卷積神經網路實現MNIST手寫字型識別

程式碼中./data/mnist/input_data/為真實MNIST資料集的路徑 import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data # 定義

[AI教程]TensorFlow入門訓練卷積網路模型解決分類問題

介紹 1.相關包匯入 // An highlighted block import math import numpy as np import h5py import matplotlib.pyplot as plt import scipy from PI

tensorflow入門經典教程+搭建神經網路

https://news.cnblogs.com/n/600330/   筆記: (1)理解佔位符 佔位符和 feed_dict   我們迄今為止所做的計算一直很乏味:沒有機會獲得輸入,所以它們總是輸出相同的東西。一個實用的應用可能涉及構建這樣一個計算圖:它接受輸入,以

TensorFlow入門訓練mnist資料集

import sys,os import numpy as np import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.

Tensorflow手寫數字識別簡單神經網路分類與CNN分類效果對比

用Tensorflow進行深度學習和人工智慧具有開發簡單,建模速度快,準確度高的優點。作為學習影象識別分類的入門,手寫輸入數字識別是個很好的例子。 MNIST包中共有60000個手寫數字筆跡灰度影象作為訓練集,每張手寫數字筆跡圖片均已儲存為28*28畫素,同時還有一個la

tensorflow入門簡單神經網路實現)

tensorflow 詳細的介紹可以看極客學院的tensorflow的官網: http://wiki.jikexueyuan.com/project/tensorflow-zh/get_started/introduction.html 官網上講解的比較清楚。。。 這裡採用

TensorFlow入門三:tensorflow手寫數字識別進階-卷積神經網路

一、基礎知識 基礎知識可以跳過,可以直接看後面的程式碼實現,碰到問題回頭來查 1.邊界檢測示例 假如你有一張如下的影象,你想讓計算機搞清楚影象上有什麼物體,你可以做的事情是檢測影象的垂直邊緣和水平邊緣。 如下是一個6*6的灰度影象,構造一個3*3的矩陣,在卷積

TensorFlow實現CNN卷積神經網路對手寫數字集mnist的模型訓練

mnist手寫數字集相當於是TensorFlow應用中的Helloworld。 在學習了TensorFlow的卷積神經網路應用之後,今天就分步解析一下其應用過程  一、mnist手寫數字資料集         MN

TensorFlow卷積神經網路(CNN)實現MNIST資料集分類

import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist=input_data.read_data_sets('MNIST_data',one_hot=True) #每

深度學習:Keras入門(二)卷積神經網路(CNN)

說明:這篇文章需要有一些相關的基礎知識,否則看起來可能比較吃力。 1.卷積與神經元          1.1 什麼是卷積?          簡單來說,卷積(或內積)就是一種先把對應位置相乘然後再把結果相加的運算。(具體含義或者數學公式可以查閱相關資料)      

深度學習入門——利用卷積神經網路訓練CIFAR—10資料集

CIFAR-10資料集簡介 CIFAR-10是由Hinton的學生Alex Krizhevsky和Ilya Sutskever整理的一個用於普適物體的小型資料集。它一共包含10個類別的RGB彩色圖片:飛機、汽車、鳥類、貓、鹿、狗、蛙類、馬、船: 資料集包含50000張訓練圖片和1000

tensorflow卷積神經網路

卷積神經網路CNN(convolutional neural networks,CNN)是一種類似於人工神經網路的深度學習模型或多層感知機,常用在影象分類、目標檢測、影象語義分割等領域,隨著大規模影象資料的產生以及計算機硬體(特別是GPU)的飛速發展,其強大的特徵學習與分類能

TensorFlow實現簡單神經網路

本文首發於我的個人部落格QIMING.INFO,轉載請帶上鍊接及署名。 在上文(TensorFlow快速上手)中,我們介紹了TensorFlow中的一些基本概念,並實現了一個線性迴歸的例子。 本文我們趁熱打鐵,接著用TensorFlow實現一下神經網路吧。 Te

深度學習卷積神經網路入門(2)

卷積神經網路入門學 作者:hjimce 卷積神經網路演算法是n年前就有的演算法,只是近年來因為深度學習相關演算法為多層網路的訓練提供了新方法,然後現在電腦的計算能力已非當年的那種計算水平,同時現在的訓練資料很多,於是神經網路的相關演算法又重新火了起來,因此卷積神經網路就又

Tensorflow簡單神經網路解決Kaggle比賽Titanic問題

  又到了假期,忙碌了一個學期,終於可以休息一下了。   一直想再Kaggle上參加一次比賽,在學校要上課,還跟老師做個專案,現在有時間了,就馬上用Kaggle的入門比賽試試手。   一場比賽,總的來說收穫不小,平時學習的時候總是眼高手低,結果中間出現令人吐

深度學習卷積神經網路CNN及tensorflow程式碼實現示例詳細介紹

一、CNN的引入 在人工的全連線神經網路中,每相鄰兩層之間的每個神經元之間都是有邊相連的。當輸入層的特徵維度變得很高時,這時全連線網路需要訓練的引數就會增大很多,計算速度就會變得很慢,例如一張黑白的 28×28 的手寫數字圖片,輸入層的神經元就有784個,如下圖所示:

tensorflow計算模型資料模型會話模型與簡單神經網路樣例

** 1.tf計算模型——計算圖 ** #定義兩個不同的圖,說明不同圖中張量無關 import tensorflow as tf g1 = tf.Graph() with g1.as_default(): v = tf.get_variable("v", [1], i