1. 程式人生 > >前饋神經網絡練習:使用tensorflow進行葡萄酒種類識別

前饋神經網絡練習:使用tensorflow進行葡萄酒種類識別

過擬合 歸一化 nim shape election 發現 tde 創建 NPU


技術分享圖片


數據處理

樣本數據描述

樣本數據集是double類型的178 * 14矩陣,第一列表示酒所屬類別,後面13列分別表示當前樣本的13個屬性:

1) Alcohol

2) Malic acid

3) Ash

4) Alcalinity of ash

5) Magnesium

6) Total phenols

7) Flavanoids

8) Nonflavanoid phenols

9) Proanthocyanins

10) Color intensity

11) Hue

12) OD280/OD315 of diluted wines

13) Proline

技術分享圖片

數據預處理

將文件內容讀入矩陣,由於標簽有三類,分別是1、2、3,於是進行二進制化。

由於各個特征的值差距較大,在進行訓練的時候收斂的速度極慢可能會導致模型無法學習到可靠參數,於是要進行特征縮放,在此處選擇均值歸一化

技術分享圖片

下圖給出處理後的數據信息

技術分享圖片 技術分享圖片 技術分享圖片

技術分享圖片

其中可以看到,在沒有進行特征縮放的時候,數據間的範圍差距過大,在進行歸一化後數據間的範圍差距明顯縮小,並且所有的特征值均在-1到1之間

數據的使用

按照8:2比例,將數據劃分為訓練數據和測試數據;訓練數據部分用來訓練模型參數,測試部分用來驗證模型效果。

下面的代碼起到按照8:2比例隨機分割數據的作用:

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2)

模型

構建模型

創建一個含有一個隱藏層的前饋神經網絡,由於特征有13個,所以網絡的輸入節點有13個,添加一個隱藏層,使其含有50個節點,由於葡萄酒的種類有3種,故,網絡有三個輸出節點

技術分享圖片

相關參數:

隱藏層

l1 = add_layer(xs, 13, 50, l1, activation_function=tf.nn.tanh) 

輸出層

prediction = add_layer(l1, 50, 3, l2, activation_function=tf.nn.softmax)

設定學習率為0.5

train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

避免過擬合采用Dropout

sess.run(train_step, feed_dict={xs: X_train, ys: y_train, keep_prob: .5})

整體結構

采用tensorboard繪制出整個神經網絡的圖結構

技術分享圖片

技術分享圖片

啟動神經網絡

進入項目的目錄,打開PowerShell,執行命令:python3 .\classify.py啟動神經網絡,在訓練的過程中叠代1000次,並每50次輸出一下此時的準確率

for i in range(1000):
    # 訓練
    sess.run(train_step, feed_dict={xs: X_train, ys: y_train, keep_prob: .5})
    if i % 50 == 0:
        # 查看loss
        train_result = sess.run(merged, feed_dict={xs: X_train, ys: y_train, keep_prob: 1})
        test_result = sess.run(merged, feed_dict={xs: X_test, ys: y_test, keep_prob: 1})
        train_writer.add_summary(train_result, i)
        test_writer.add_summary(test_result, i)
        # 輸出準確率
        print(compute_accuracy(X_test, y_test))


結果

輸出的準確率

在訓練的過程中叠代1000次中每50次輸出一下此時的準確率

技術分享圖片

查看損失函數圖像

借助tensorboard,將訓練過程可視化,在代碼執行完畢後在項目目錄中生成“logs”文件夾,可視化文件存在此處。

在項目目錄中的PowerShell中執行命令tensorboard --logdir=‘logs‘得到可視化文件鏈接

技術分享圖片

在瀏覽器中輸入此網址(http://lichaoxing-PC:6006),可以得到詳細的可視化圖形

技術分享圖片

準確率圖像

在測試的時候,繪制準確率與叠代次數(1000次)的函數圖像;由於模型的收斂速度比較快,無法觀察出收斂過程,於是可以在繪制一個叠代次數在0到100間的圖像便於觀察收斂過程

技術分享圖片

遇到的問題

在搭建好神經網絡模型後,直接將沒有進行特征縮放的數據輸入模型,結果發現模型收斂速度極慢,導致模型失效,測試輸出的準確率非常低

技術分享圖片

觀察loss函數圖像,可以看出模型並沒有收斂的趨勢

技術分享圖片

解決此問題的辦法就是進行特征縮放,可以參考:https://blog.csdn.net/u012328159/article/details/51030366


代碼

classify.py

#coding:utf-8
import tensorflow as tf
from w_i_n_e import wine
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelBinarizer
#import pylab as pl
from plot import plot_it

# 歸一化方法
def Normalize(data):
    m = np.mean(data)
    mx = max(data)
    mn = min(data)
    return [(float(i) - m) / (mx - mn) for i in data]

# 加載數據
mywine = wine(./wine.all.txt)
X = mywine.data
# 特征縮放---歸一化
for _ in range(13):
    X[:, _] = Normalize(X[:, _])
y = mywine.target
y = LabelBinarizer().fit_transform(y)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2)

# add_layer
def add_layer(inputs, in_size, out_size, layer_name, activation_function=None, ):
    Weights = tf.Variable(tf.random_normal([in_size, out_size]))
    biases = tf.Variable(tf.zeros([1, out_size]) + 0.1, )
    Wx_plus_b = tf.matmul(inputs, Weights) + biases
    # dropout---消除過擬合
    Wx_plus_b = tf.nn.dropout(Wx_plus_b, keep_prob)
    if activation_function is None:
        outputs = Wx_plus_b
    else:
        outputs = activation_function(Wx_plus_b, )
    tf.summary.histogram(layer_name + /outputs, outputs)
    return outputs
# 評估---準確率
def compute_accuracy(v_xs, v_ys):
    global prediction
    y_pre = sess.run(prediction, feed_dict={xs: v_xs, keep_prob: 1})
    correct_prediction = tf.equal(tf.argmax(y_pre,1), tf.argmax(v_ys,1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    result = sess.run(accuracy, feed_dict={xs: v_xs, ys: v_ys, keep_prob: 1})
    return result

# 定義網絡輸入的占位符
keep_prob = tf.placeholder(tf.float32)
xs = tf.placeholder(tf.float32, [None, 13])
ys = tf.placeholder(tf.float32, [None, 3])

# 添加輸出圖層
l1 = add_layer(xs, 13, 50, l1, activation_function=tf.nn.tanh)
prediction = add_layer(l1, 50, 3, l2, activation_function=tf.nn.softmax)


# 損失函數---loss
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction),
                                              reduction_indices=[1]))  # loss
tf.summary.scalar(loss, cross_entropy)
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

sess = tf.Session()
merged = tf.summary.merge_all()
# summary
train_writer = tf.summary.FileWriter("logs/train", sess.graph)
test_writer = tf.summary.FileWriter("logs/test", sess.graph)

init = tf.global_variables_initializer()
sess.run(init)
A = []
I = []
for i in range(1000):
    # 訓練
    sess.run(train_step, feed_dict={xs: X_train, ys: y_train, keep_prob: .5})
    if i % 50 == 0:
        # 查看loss
        train_result = sess.run(merged, feed_dict={xs: X_train, ys: y_train, keep_prob: 1})
        test_result = sess.run(merged, feed_dict={xs: X_test, ys: y_test, keep_prob: 1})
        train_writer.add_summary(train_result, i)
        test_writer.add_summary(test_result, i)
        # 輸出準確率
        print(compute_accuracy(X_test, y_test))
    A.append(compute_accuracy(X_test, y_test))
    I.append(i)

plot_it(I, A)

w_i_n_e.py

#coding:utf-8
from numpy import *

# wine數據結構---讀入數據到矩陣
class wine(object):

    data = zeros((178,13))
    target = zeros((178,1))
    def __init__(self, filename):
        self.filename = filename
        
        fl = open(self.filename, r)
        lines = fl.readlines()
        row = 0
        for line in lines:
            list = line.strip(\n).split(,)
            wine.data[row:] = list[1:14]
            wine.target[row:] = list[0:1]
            row+=1
        fl.close()
    

file.py

#coding:utf-8

from w_i_n_e import wine
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelBinarizer
import numpy as np

mywine = wine(./wine.all.txt)
X = mywine.data
y = mywine.target
print(---------------------------)
print("特征矩陣:", X.shape)
print(---------------------------)
print("標簽向量:", y.shape)
print(---------------------------)
print("y原始:\n", y)
y = LabelBinarizer().fit_transform(y)
print("y二進制化:\n", y)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2)

print(---------------------------)
print("特征矩陣:", X.shape)
print(---------------------------)
print("標簽矩陣:", y.shape)

def Normalize(data):
    m = np.mean(data)
    mx = max(data)
    mn = min(data)
    return [(float(i) - m) / (mx - mn) for i in data]

print("X原始:\n")
print(X)

for _ in range(13):
    X[:, _] = Normalize(X[:, _])
print("X歸一化處理:\n")
print(X)

plot.py

#coding:utf-8

import matplotlib.pyplot as plt

def plot_it(x, y):
    plt.figure(figsize=(7,5))
    plt.subplot(211)  #兩行一列,第一個圖
    plt.plot(x, y, lw = 1.5,label = i:1-1000) 
    plt.grid(True)
    plt.legend(loc = 0)
    plt.ylabel(accuracy)
    plt.title(accuracy-i)


    plt.subplot(212) #兩行一列.第二個圖
    plt.plot(x[0: 101], y[0: 101],g, lw = 1.5, label = i:1-100)
    plt.grid(True)
    plt.legend(loc = 0)
    plt.xlabel(i)
    plt.ylabel(accuracy)
    plt.show()

readme.txt

#啟動
python3 classify.py

#tensorboard
tensorboard --logdir=‘logs‘


本節完......

前饋神經網絡練習:使用tensorflow進行葡萄酒種類識別