通過本文你可以學會神經網絡最基本的用法,可以對tensorflow用法有初步的瞭解,實現神經網絡入門,適用於有着在機器學習/或者深度學習有着理論基礎,擁有一定python編程基礎但是對神經網絡實踐缺少經驗的coder,通過閱讀並且自己完成本篇博客中的代碼小白也能學會如何利用神經網絡來實現簡單的分類任務。這一講源碼在我的github,地址:https://github.com/JohnLeek/Tensorflow-study,源碼文件爲day1_iris_classfiction.py,覺得不錯可以給個Star。
一、環境配置
這裏需要用到的第三方包有numpy,pandas,matplotlib,sklearn,注意的是tensorflow用的是2.0版本,不涉及圖像GPU和CPU版本隨意選擇,讀者可先用pip命令安裝好所需要的包,tensorflow2.0的安裝配置見我這篇博客,https://blog.csdn.net/JohnLeeK/article/details/104508885,開發工具選擇pycharm,pycharm中配置tensorflow運行環境可以參考我的這篇matplot配置博客,https://blog.csdn.net/JohnLeeK/article/details/99582355,大同小異,也可自行百度解決。
二、鳶尾花數據集展示與說明
from sklearn import datasets
from pandas import DataFrame
import pandas as pd
#.data返回特徵值
x_data = datasets.load_iris().data
#.target 返回標籤
y_data = datasets.load_iris().target
print("x_data from datasets: \n",x_data)
print("y_data from datasets: \n",y_data)
x_data = DataFrame(x_data,columns=['花萼長度','花萼寬度','花瓣長度','花瓣寬度'])
pd.set_option('display.unicode.east_asian_width',True)
x_data['類別'] = y_data
print("x_data add a column: \n",x_data)
結果:
可知數據集提供了死個鳶尾花屬性,分別爲花萼長度、花萼寬度、花瓣長度、花瓣寬度,0,1,2分別對應不同的鳶尾花品種。到這裏我們就可以設計出來本次鳶尾花分類的神經網絡模型,輸入層4個神經元對應鳶尾花數據集的4個特徵,輸出層3個神經元對應鳶尾花的3個分類。
好了有了數據集的準備,並且我們也搭建出來了簡單的神經網絡模型(不包括偏置神經元,通常在設計神經網絡時會忽略,bias)。
三、本次實驗中用到的函數介紹
tf.cast(data,tf.float32)
這個函數用於將我們的數據轉化爲可供tensorflow訓練和測試使用的張量(Tensor),通常我們讀取的數據爲numpy格式或者是python自帶的數據形式,但是在喂入神經網絡的時候需要做轉化,使用cast函數即可,data爲我們要轉化的數據,tf.float32爲轉化之後的數據類型。
2、tf.data.Dataset.from_tensor_slices
tf.data.Dataset.from_tensor_slices(tensor1,tensor2)
這個函數會將我們的訓練接Tensor1和tensor2做標籤對應關係,以方便神經網絡訓練,注意tensor1和tensor2維度必須相同。
tf.Variable(
initial_value=None, trainable=None, validate_shape=True, caching_device=None,
name=None, variable_def=None, dtype=None, import_scope=None, constraint=None,
synchronization=tf.VariableSynchronization.AUTO,
aggregation=tf.compat.v1.VariableAggregation.NONE, shape=None
)
這裏我們只使用initial_value,這個函數會將我們傳入的tensor或者數標記爲“可訓練”,可以在訓練的過程中更新我們傳入的參數。
tf.random.truncated_normal(
shape, mean=0.0, stddev=1.0, dtype=tf.dtypes.float32, seed=None, name=None
)
shape參數指定我們生成的神經元形狀用list傳入,如[4,3]指定生成4的神經元,3爲輸出,mean爲生成隨機數的中指,stddev爲方差,seed爲隨機數種子。
tf.GradientTape(
persistent=False, watch_accessed_variables=True
)
tf.nn.softmax(
logits, axis=None, name=None
)
神經網絡最後的輸出爲矩陣的形式,爲了獲得我們期待的形式我們使用softmax讓輸出符合概率分佈
tf.one_hot(
indices, depth, on_value=None, off_value=None, axis=None, dtype=None, name=None
)
將標籤轉化爲獨熱碼性質,注意depth,這裏指定分類,鳶尾花分類是3,所以depth=3
四、正式開始工作
導入我們要用到的模塊:
import tensorflow as tf
from sklearn import datasets
from matplotlib import pyplot as plt
import numpy as np
剛纔我們已經看過鳶尾花數據集結構了,現在我們導入數據集
x_data = datasets.load_iris().data
y_data = datasets.load_iris().target
首先官方給出的數據集是有順序的,所以我們需要打亂數據集順序,如同我們人認識這個世界的時候一樣,知識都是雜亂無章的涌入我們大腦的,避免陷入局部最優解,可以獲得更高的分類準確率。
###seed爲隨機種子,保證每次生成的隨機數一樣
###方便你得到的結果和我一樣
np.random.seed(116)
np.random.shuffle(x_data)
np.random.seed(116)
np.random.shuffle(y_data)
tf.random.set_seed(116)
這樣我們就保證了數據集的亂序,而且亂序用的seed是一樣的,所以都有同樣的順序。
接下來我們拆分數據集和訓練集,指定前120組數據爲訓練集,剩餘的30組數據爲測試集,通常訓練集大小爲總數據集大小的60%--70%。
x_train = x_data[:-30]
y_train = y_data[:-30]
x_test = x_data[-30:]
y_test = y_data[-30:]
tensorflow中一般默認數據類型爲float32,但是我們讀入的數據可能不是,所以我們做一下強制類型轉換,保證數據的類型統一。
x_train = tf.cast(x_train,tf.float32)
x_test = tf.cast(x_test,tf.float32)
我們要實現輸入數據就能得到對應的輸出,還需要將特徵值和標籤匹配。
'''
匹配輸入特徵還有標籤
batch爲喂入神經神經網絡每組數據大小
'''
train_db = tf.data.Dataset.from_tensor_slices((x_train,y_train)).batch(32)
test_db = tf.data.Dataset.from_tensor_slices((x_test,y_test)).batch(32)
這裏batch爲喂入神經網絡的數據集大小,我們設置爲32,這樣就是分四次喂入神經網絡。完成了基本準備工作後,我們就開始利用tensorflow搭建神經網絡。
'''
搭建神經網絡,4個特徵值,輸入層爲4個神經元;3分類,所以輸出層爲3個神經元
seed保證生成的隨機數相同,實際項目不需要
Variable標記訓練參數
'''
w1 = tf.Variable(tf.random.truncated_normal([4,3],stddev=0.1,seed=1))
b1 = tf.Variable(tf.random.truncated_normal([3],stddev=0.1,seed=1))
接下來我們設置學習率,和迭代次數
lr = 0.1#學習率
train_loss_result = []#記錄每輪訓練之後的loss
test_acc = []#模型準確度
epoch = 500#每輪訓練次數
loss_all = 0#每輪分爲4step,記錄四個step生成的4個loss和
神經網絡訓練部分
神經網絡訓練部分
for epoch in range(epoch): #數據集別循環每個epoch遍歷一次數據集
for step,(x_train,y_train) in enumerate(train_db): #batch級別循環,每個step循環一個batch
with tf.GradientTape() as tape: #梯度下降求得參數值
y = tf.matmul(x_train,w1) + b1 #函數表達式 y = xw + b
y = tf.nn.softmax(y)#使輸出符合概率分佈
y_ = tf.one_hot(y_train,depth = 3)#將標籤轉化爲獨熱碼,方便求loss和accuracy
loss = tf.reduce_mean(tf.square(y_-y))#採用均方誤差損失函數mes = mean(sum(y-out)^2)
loss_all += loss.numpy()#將每個step計算得出的loss累加,爲後續求loss平均值提供數據
#計算w1和b1梯度
grads = tape.gradient(loss,[w1,b1])
#更新梯度
w1.assign_sub(lr*grads[0])
b1.assign_sub(lr*grads[1])
#每個epoch打印下loss
print("Epoch: {},loss: {}".format(epoch,loss_all/4))
#保存每個step的平均值
train_loss_result.append(loss_all/4)
訓練完成之後我們便可以驗證模型準確率了。
'''
total_correct爲預測正確的樣本個數
total_number爲測試樣本總數
'''
total_correct,total_number = 0,0
for x_test,y_train in test_db:
y = tf.matmul(x_test, w1) + b1
y = tf.nn.softmax(y)
pred = tf.argmax(y, axis=1) # 返回y中的最大值索引,即預測分類
# 將pred轉化爲y_test數據類型
pred = tf.cast(pred, dtype=y_test.dtype)
# 如果分類正確,correct = 1 否則爲0,將bool類型結果轉化爲int
correct = tf.cast(tf.equal(pred, y_test), dtype=tf.int32)
# 將每個batch的correct數加起來
correct = tf.reduce_sum(correct)
# 將所有batch中的correct加起來
total_correct += int(correct)
# total_number爲測試的總樣本數,即x_test的行數,shape[0]返回行數
total_number += x_test.shape[0]
# 計算準確率
acc = total_correct / total_number
test_acc.append(acc)
print("Test_acc:", acc)
print("這是一條分割線------------------********************++++++++++++++++++")
結果可視化:爲了方便我們觀察模型訓練結果我們使用matplotlib將準確率還有損失函數更新情況繪製成圖片。
#繪製loss曲線
plt.title("Losss Function Curve")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.plot(train_loss_result,label="$Loss$")# 逐點畫出trian_loss_results值並連線,連線圖標是Loss
plt.legend()
plt.savefig("./loss")
#繪製Accuracy曲線
plt.title("Acc Curve")
plt.xlabel("Epoch")
plt.ylabel("Acc")
plt.plot(test_acc,label="$Accuracy$") # 逐點畫出test_acc值並連線,連線圖標是Accuracy
plt.legend
plt.savefig("./acc")
五、結果展示
從圖中可以看出在我們完成500輪訓練之後,分類準確率達到了100%,總的來說模型準確率不錯,接下來看看繪製的Accuracy和Loss曲線。
可以看到在200輪左右模型基本得到了最優解,Loss也是一直下降,至此我們的第一個深度學習模型就已經搭建完畢。隨後的博客中我會持續更新tensorflow2.0學習筆記,從簡單的神經網絡到CNN到RNN再到GAN。如果你覺得我的博客對你有幫助,別忘記點贊,你的點贊是我更新的動力!本節源碼github地址:https://github.com/JohnLeek/Tensorflow-study,源碼文件爲:day1_iris_classfiction.py,覺得不錯可以給個Star。