感知机——鸢尾花 包含代码
感知機
1 人工智能三學派
?我們常說的人工智能,就是讓機器具備人的思維和意識。人工智能主要有三個學派,即行為主義、符號主義和連接主義。
??行為主義:是基于控制論的,是在構建感知、動作的控制系統。單腳站立是行為主義一個典型例子,通過感知要摔倒的方向,控制兩只手的動作,保持身體的平衡。這就構建了一個感知、動作的控制系統,是典型的行為主義。
?? 符號主義:基于算數邏輯表達式。即在求解問題時,先把問題描述為表達式,再求解表達式。例如在求解某個問題時,利用 if case 等條件語句和若干計算公式描述出來,即使用了符號主義的方法,如專家系統。符號主義是能用公式描述的人工智能,它讓計算機具備了理性思維。
??連接主義:仿造人腦內的神經元連接關系,使人類不僅具備理性思維,還具備無法用公式描述的感性思維,如對某些知識產生記憶。
圖 1.1 展示了人腦中的一根神經元,其中紫色部分為樹突,其作為神經元的輸入。黃色部分為軸突,其作為神經元的輸出。人腦就是由 860 億個這樣的神經元首尾相接組成的網絡。
? 基于連接主義的神經網絡模仿上圖的神經元,使計算機具有感性思維。
?隨著我們的成長,大量的數據通過視覺、聽覺涌入大腦,使我們的神經網絡
?連接,也就是這些神經元連接線上的權重發生了變化,有些線上的權重增強了, 有些線上的權重減弱了。如圖 1.3 所示。
2 神經網絡設計過程
?? 我們要用計算機模仿剛剛說到的神經網絡連接關系,讓計算機具備感性思維。
??首先,需要準備數據,數據量越大越好,要構成特征和標簽對。如要識別貓, 就要有大量貓的圖片和這個圖片是貓的標簽,構成特征標簽對。 隨后,搭建神經網絡的網絡結構,并通過反向傳播,優化連線的權重,直到 模型的識別準確率達到要求,得到最優的連線權重,把這個模型保存起來。
??最后,用保存的模型,輸入從未見過的新數據,它會通過前向傳播,輸出概 率值,概率值最大的一個,就是分類或預測的結果。圖 2.1 展示了搭建與使用神 經網絡模型的流程。
??采用鳶尾花數據集,此數據集包含鳶尾花花萼長、花萼寬、花瓣長、 花瓣寬及對應的類別。其中前 4 個屬性作為輸入特征,類別作為標簽,0 代表狗尾草鳶尾,1 代表雜色鳶尾,2 代表弗吉尼亞鳶尾。人們通過對數據進行分析總結出了規律:通過測量花的花萼長、花萼寬、花瓣長、花瓣寬,可以得出鳶尾花的類別(如:花萼長>花萼寬且花瓣長/花瓣寬>2,則雜色鳶尾)。
??由上述可知,這邊采用搭建神經網絡的辦法對其進行分類,即將鳶尾花花萼長、花萼寬、花瓣長、花瓣寬四個輸入屬性喂入搭建好的神經網絡,網絡優化參數得到模型,輸出分類結果。
2.2 網絡搭建與訓練
??搭建包含輸入層與輸出層的神經網絡模型,通過對輸入值乘權值,并于偏置值求和的方式得到輸出值,圖示如下。
?? 由圖 2.2 可知輸出 y = x ?w+ b ,即所有的輸入 x 乘以各自線上的權重 w 求和加上偏置項b得到輸出y 。由 2.1部分對數據集的介紹可知,輸入特征 x 形狀應為(1,4)即 1 行 4 列,輸出 y 形狀應為(1,3)即 1 行 3 列,w 形狀應為(4,3)即 4 行 3 列,b 形狀應為(3, )即有 3 個偏置項。
?? 搭建好基本網絡后,需要輸入特征數據,并對線上權重 w 與偏置b 進行初始化。搭建的神經網絡如圖 2.3 所示, w,b 初始化矩陣如圖 2.4 所示。在這里,我們輸入標簽為 0 的狗尾草鳶尾。
??有了輸入數據與線上權重等數據,即可按照 y = x ? w + b 方式進行前向傳播, 計算過程如圖 2.5 所示。
*圖 2.5 前向傳播計算過程*?? 圖 2.5 中輸出 y 中,1.01 代表 0 類鳶尾得分,2.01 代表 1 類鳶尾得分,0.66 代表2 類鳶尾得分。通過輸出 y 可以看出數值最大(可能性最高)的是 1 類鳶尾,而不是標簽0類鳶尾。這是由于最初的參數 w 和b 是隨機產生的,現在輸出的結果是蒙的。 為了修正這一結果,我們用損失函數,定義預測值 y 和標準答案(標簽) _ y 的 差距,損失函數可以定量的判斷當前這組參數 w 和b 的優劣,當損失函數最小 時,即可得到最優w的值和b的值。
?? 損失函數的定義有多種方法,均方誤差就是一種常用的損失函數,它計算每個前向傳播輸出 y 和標準答案 _ y的差求平方再求和再除以 n 求平均值,表征了
網絡前向傳播推理結果和標準答案之間的差距。
?? 通過上述對損失函數的介紹,其目的是尋找一組參數 w 和b 使得損失函數最小。為達成這一目的,我們采用梯度下降的方法。損失函數的梯度表示損失函數 對各參數求偏導后的向量,損失函數梯度下降的方向,就是是損失函數減小的方向。梯度下降法即沿著損失函數梯度下降的方向,尋找損失函數的最小值,從而得到最優的參數。梯度下降法涉及的公式如下
??????? ?? wt+1 = wt ?lr?loss/?wt
??????? ?? bt+1 = bt ?lr?loss/?bt
???????? ? wt+1x+bt+1 → y
? 上式中,lr 表示學習率,是一個超參數,表征梯度下降的速度。如學習率設置 過小,參數更新會很慢,如果學習率設置過大,參數更新可能會跳過最小值。
? 上述梯度下降更新的過程為反向傳播,下面通過例子感受反向傳播。利用如 下公式對參數 w 進行更新。
? ? ? ? ? ? ? wt+1 = wt ?lr?loss/?wt
? 設損失函數為(w+1)2,則其對w的偏導數為2w+2。設w在初始化時被隨機初始化為 5,學習率設置為 0.2。則我們可按上述公式對w進行更新:第一次參數為 5,按上式計算即5?0.2×(2×5+ 2) =2.6。同理第二次計算得到參數為 1.16,第三次計算得到參數為 0.296…… 畫出損失函數(w+1)2的圖像,可知w =-1時損失函數最小,我們反向傳播優化參數的目的即為找到這個使損失函數最小的w =-1值。
3.添加獨熱碼標簽
? 可用 tf.one_hot(待轉換數據,depth=幾分類)函數實現用獨熱碼表示標簽,在分類問題中很常見。標記類別為為 1 和 0,其中 1 表示是,0 表示非。如在鳶尾花分類任務中,如果標簽是 1,表示分類結果是 1 雜色鳶尾,其用把它用獨熱碼表示就是 0,1,0,這樣可以表示出每個分類的概率:也就是百分之 0 的可能是 0 狗尾草鳶尾,百分百的可能是 1 雜色鳶尾,百分之 0 的可能是弗吉尼亞鳶尾。舉例如下:
? 輸出結果:tf.Tensor([[0. 1. 0.] [1. 0. 0.] [0. 0. 1.]], shape=(3, 3), dtype=float32)
? 索引從 0 開始,待轉換數據中各元素值應小于 depth,若帶轉換元素值大于等于depth,則該元素輸出編碼為 [0, 0 … 0, 0]。即 depth 確定列數,待轉換元素的個數確定行數。舉例如下:
classes = 3 labels = tf.constant([1,4,2]) # 輸入的元素值 4 超出 depth-1 output = tf.one_hot(labels,depth=classes) print(output)輸出結果:
? tf.Tensor([[0. 1. 0.] [0. 0. 0.] [0. 0. 1.]], shape=(3, 3), dtype=float32) 即元素 4 對應的輸出編碼為[0. 0. 0.]。
3.2? 可利用 tf.nn.softmax( )函數使前向傳播的輸出值符合概率分布,進而與獨熱碼形式的標簽作比較,其計算公式為 :
其中yi 是前向傳播的輸出。在前一部分,我們得到了前向傳播的輸出值,分別為 1.01、2.01、-0.66,通過上述計算公式,可計算對應的概率值:
上式中,0.256表示為0類鳶尾的概率是 25.6%,0.695 表示為1類鳶尾的概率是
69.5%,0.048 表示為2類鳶尾的概率是4.8%程序實現如下:
輸出結果:After softmax, y_pro is:
? ? tf.Tensor([0.25598174 0.69583046 0.0481878], shape=(3,), dtype=float32)
與上述計算結果相同。
4總結
源碼1:(源碼二,是20行解決這個問題)
# 利用鳶尾花數據集,實現前向傳播、反向傳播,可視化loss曲線# 導入所需模塊 import tensorflow as tf from sklearn import datasets #導入數據集 from matplotlib import pyplot as plt import numpy as np #數組 import time # 導入數據,分別為輸入特征和標簽 x_data = datasets.load_iris().data y_data = datasets.load_iris().target# 隨機打亂數據(因為原始數據是順序的,順序不打亂會影響準確率) # seed: 隨機數種子,是一個整數,當設置之后,每次生成的隨機數都一樣 np.random.seed(116) # 使用相同的seed,保證輸入特征和標簽一一對應 np.random.shuffle(x_data) np.random.seed(116) np.random.shuffle(y_data) tf.random.set_seed(116)# 將打亂后的數據集分割為訓練集和測試集,訓練集為前120行,測試集為后30行 x_train = x_data[:-30] y_train = y_data[:-30] x_test = x_data[-30:] y_test = y_data[-30:]# 轉換x的數據類型,否則后面矩陣相乘時會因數據類型不一致報錯 x_train = tf.cast(x_train, tf.float32) x_test = tf.cast(x_test, tf.float32)# from_tensor_slices函數使輸入特征和標簽值一一對應。(把數據集分批次,每個批次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)# 生成神經網絡的參數,4個輸入特征故,輸入層為4個輸入節點;因為3分類,故輸出層為3個神經元 # 用tf.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_results = [] # 將每輪的loss記錄在此列表中,為后續畫loss曲線提供數據 test_acc = [] # 將每輪的acc記錄在此列表中,為后續畫acc曲線提供數據 epoch = 500 # 循環500輪 loss_all = 0 # 每輪分4個step,loss_all記錄四個step生成的4個loss的和# 訓練部分 now_time = time.time() ##2##for epoch in range(epoch): #數據集級別的循環,每個epoch循環一次數據集for step, (x_train, y_train) in enumerate(train_db): #batch級別的循環 ,每個step循環一個batchwith tf.GradientTape() as tape: # with結構記錄梯度信息y = tf.matmul(x_train, w1) + b1 # 神經網絡乘加運算y = tf.nn.softmax(y) # 使輸出y符合概率分布(此操作后與獨熱碼同量級,可相減求loss)y_ = tf.one_hot(y_train, depth=3) # 將標簽值轉換為獨熱碼格式,方便計算loss和accuracyloss = tf.reduce_mean(tf.square(y_ - y)) # 采用均方誤差損失函數mse = mean(sum(y-out)^2)loss_all += loss.numpy() # 將每個step計算出的loss累加,為后續求loss平均值提供數據,這樣計算的loss更準確# 計算loss對各個參數的梯度grads = tape.gradient(loss, [w1, b1])# 實現梯度更新 w1 = w1 - lr * w1_grad b = b - lr * b_gradw1.assign_sub(lr * grads[0]) # 參數w1自更新b1.assign_sub(lr * grads[1]) # 參數b自更新# 每個epoch,打印loss信息print("Epoch {}, loss: {}".format(epoch, loss_all/4))train_loss_results.append(loss_all / 4) # 將4個step的loss求平均記錄在此變量中loss_all = 0 # loss_all歸零,為記錄下一個epoch的loss做準備# 測試部分# total_correct為預測對的樣本個數, total_number為測試的總樣本數,將這兩個變量都初始化為0total_correct, total_number = 0, 0for x_test, y_test in test_db:# 使用更新后的參數進行預測y = tf.matmul(x_test, w1) + b1y = 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]# 總的準確率等于total_correct/total_numberacc = total_correct / total_numbertest_acc.append(acc)print("Test_acc:", acc)print("--------------------------") total_time = time.time() - now_time ##3## print("total_time", total_time) ##4### 繪制 loss 曲線 plt.title('Loss Function Curve') # 圖片標題 plt.xlabel('Epoch') # x軸變量名稱 plt.ylabel('Loss') # y軸變量名稱 plt.plot(train_loss_results, label="$Loss$") # 逐點畫出trian_loss_results值并連線,連線圖標是Loss plt.legend() # 畫出曲線圖標 plt.show() # 畫出圖像# 繪制 Accuracy 曲線 plt.title('Acc Curve') # 圖片標題 plt.xlabel('Epoch') # x軸變量名稱 plt.ylabel('Acc') # y軸變量名稱 plt.plot(test_acc, label="$Accuracy$") # 逐點畫出test_acc值并連線,連線圖標是Accuracy plt.legend() plt.show()源碼2:(實現效果同上)
import tensorflow as tf from tensorflow.keras.layers import Dense from tensorflow.keras import Model from sklearn import datasets import numpy as npx_train = datasets.load_iris().data y_train = datasets.load_iris().targetnp.random.seed(116) np.random.shuffle(x_train) np.random.seed(116) np.random.shuffle(y_train) tf.random.set_seed(116)class IrisModel(Model):def __init__(self):super(IrisModel, self).__init__()self.d1 = Dense(3, activation='softmax', kernel_regularizer=tf.keras.regularizers.l2())def call(self, x):y = self.d1(x)return ymodel = IrisModel()model.compile(optimizer=tf.keras.optimizers.SGD(lr=0.1),loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),metrics=['sparse_categorical_accuracy'])model.fit(x_train, y_train, batch_size=32, epochs=500, validation_split=0.2, validation_freq=20) model.summary()總結
以上是生活随笔為你收集整理的感知机——鸢尾花 包含代码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Proteus和Keil两个软件的联合使
- 下一篇: mybatis plus 查询排序_My