前饋神經網絡練習:使用tensorflow進行葡萄酒種類識別
數據處理
樣本數據描述
樣本數據集是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進行葡萄酒種類識別