行為主義:基于控制理論,構建感知-動作控制系統;
符號主義:基于算數邏輯表達式,求解問題時候,先將問題抽象成表達式,在對表達式進行求解;
連接主義:仿生學,模仿神經元的連接關系
深度學習進行計算機神經網絡的連接關系:
1.準備數據:采集大量“特征/標簽” 數據
2.搭建網絡:搭建神經網絡結構
3.優化參數:訓練網絡獲取最佳參數(反傳)
4.應用網絡:將網絡保存為模型,輸入新數據,歷史數據模型訓 練新數據 輸入預測 結果歷史數據訓練模型使用模型推理結果用計算機仿出神經網絡連接關系,讓計算機具備感性思維。Cat(特征 , 標簽)輸出分類或預測結果(前傳)
神經網絡進行分類:
損失函數:
預測值(y)與標準答案(y_)的差距。損失函數可以定量判斷W、 b的優劣, 當損失函數輸出最小時,參數W、b會出現最優值。
梯度:
函數對各參數求偏導后的向量。 函數梯度下降方向是函數減小方向。梯度下降法:沿損失函數梯度下降的方向,尋找損失函數的最小值,得到最優參數的方法。
學習率(learning rate, lr):
當學習率設置的過小時,收斂過程將變得十分緩慢。而當學習率設置的過大時,梯度可能會在最小值附近來回震蕩,甚至可能無法收斂。
梯度下降法尋找最優參數:
import tensorflow as tf
if __name__ == '__main__':
print(tf.__version__)
w = tf.Variable(tf.constant(5,dtype=tf.float32)) # 給定一個 w的初始值
lr = 0.2 #給定學習率
epoch = 40 #迭代次數
for epoch in range(epoch):
with tf.GradientTape as tape:
loss = tf.square(w + 1) #定義損失函數
grads = tape.gradient(loss,w)# 定義損失函數對 w的求偏導數
w.assign_sub(lr * grads) # 對變量進行自減 w-=lr*grads
print("after %s epoch, wi is %f .loss is %f"%(epoch,w.numpy(),loss))
#最終目的 找到最小的loss w = -1 的最優參數
張量(tensor)
數據類型:
tf.int (tf.in 32) tf.float(tf.float 32 tf.float 64)
tf.bool (tf.constant([True,False]))
tf.string (tf.constant("fudanuniversity "))
創建一個張量 tf.constant(張量內容, dtype=數據類型(可選))
import tensorflow as tf
a=tf.constant([1,5],dtype=tf.int64)
print(a)
print(a.dtype)
print(a.shape)
將numpy的數據類型轉換為Tensor數據類型
tf. convert_to_tensor(數據名, dtype=數據類型(可選))
import tensorflow as tf
import numpy as np
a = np.arange(0, 5)
b = tf.convert_to_tensor( a, dtype=tf.int64 )
print(a)
print(b)
運行結果:
[0 1 2 3 4]
tf.Tensor([0 1 2 3 4], shape=( 5 , ), dtype=int64)
創建全為0的張量
tf. zeros(維度)
創建全為1的張量
tf. ones(維度)
創建全為指定值的張量
tf. fill(維度,指定值)
a = tf.zeros([2, 3])
b = tf.ones(4)
c = tf.fill([2, 2], 9)
print(a)
print(b)
print(c)
運行結果:
tf.Tensor([[0. 0. 0.] [0. 0. 0.]], shape=(2, 3), dtype=float32)
tf.Tensor([1. 1. 1. 1.], shape=(4, ), dtype=float32)
tf.Tensor([[9 9] [9 9]], shape=(2, 2), dtype=int32)
生成正態分布的隨機數,默認均值為0,標準差為1
tf. random.normal (維度, mean=均值, stddev=標準差)
生成截斷式正態分布的隨機數
tf. random.truncated_normal (維度, mean=均值, stddev=標準差)
在tf.truncated_normal中如果隨機生成數據的取值在(μ-2σ, μ+2σ)之外則重新進行生成,保證了生成值在均值附近。μ:均值, σ:標準差
d = tf.random.normal ([2, 2], mean=0.5, stddev=1)
print(d)
e = tf.random.truncated_normal ([2, 2], mean=0.5, stddev=1)
print(e)
運行結果:
tf.Tensor(
[[0.7925745 0.643315 ]
[1.4752257 0.2533372]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[ 1.3688478 1.0125661 ]
[ 0.17475659 -0.02224463]], shape=(2, 2), dtype=float32)
生成均勻分布隨機數 [ minval, maxval )
tf. random. uniform(維度, minval=最小值, maxval=最大值) 前閉后開區間
f = tf.random.uniform([2, 2], minval=0, maxval=1)
print(f)
?生成均勻分布隨機數 [ minval, maxval )
tf. random. uniform(維度, minval=最小值, maxval=最大值)
運行結果:
tf.Tensor(
[[0.28219545 0.15581512]
[0.77972126 0.47817433]], shape=(2, 2), dtype=float32)
強制tensor轉換為該數據類型
tf.cast (張量名, dtype=數據類型)
計算張量維度上元素的最小值
tf.reduce_min (張量名)
計算張量維度上元素的最大值
tf.reduce_max (張量名)
x1 = tf.constant ([1., 2., 3.],dtype=tf.float64)
print(x1)
x2 = tf.cast (x1, tf.int32) #強制類型轉換
print(x2)
print (tf.reduce_min(x2),tf.reduce_max(x2))
運行結果:
tf.Tensor([1. 2. 3.], shape=(3,), dtype=float64)
tf.Tensor([1 2 3], shape=(3,), dtype=int32)
tf.Tensor(1, shape=(), dtype=int32)
tf.Tensor(3, shape=(), dtype=intt32)
理解axis
在一個二維張量或數組中,可以通過調整 axis 等于0或1 控制執行維度。 axis=0代表跨行(經度, down),而axis=1代表跨列(緯度, across) 如果不指定axis,則所有元素參與計算。
計算張量沿著指定維度的平均值
tf.reduce_mean (張量名, axis=操作軸)
計算張量沿著指定維度的和
tf.reduce_sum (張量名, axis=操作軸)
x=tf.constant( [ [ 1, 2, 3],
[ 2, 2, 3] ] )
print(x)
print(tf.reduce_mean( x )) #就算全部平均值
print(tf.reduce_sum( x, axis=1 )) #按照行來計算
運行結果:
tf.Tensor([[1 2 3] [2 2 3]], shape=(2, 3), dtype=int32)
tf.Tensor(2, shape=(), dtype=int32)
tf.Tensor([6 7], shape=(2,), dtype=int32)
tf.Variable () 將變量標記為“可訓練” ,被標記的變量會在反向傳播中記錄梯度信息。神經網絡訓練中,常用該函數標記待訓練參數
tf.Variable(初始值)
w = tf.Variable(tf.random.normal([2, 2], mean=0, stddev=1))
實現兩個張量的對應元素相加
tf.add (張量1,張量2)
實現兩個張量的對應元素相減
tf.subtract (張量1,張量2)
實現兩個張量的對應元素相乘
tf.multiply (張量1,張量2)
實現兩個張量的對應元素相除
tf.divide (張量1,張量2)
a = tf.ones([1, 3]) #[1,1,1]
b = tf.fill([1, 3], 3.) #[3,3,3]
print(a)
print(b)
print(tf.add(a,b))
print(tf.subtract(a,b))
print(tf.multiply(a,b))
print(tf.divide(b,a))
運行結果:
tf.Tensor([[1. 1. 1.]], shape=(1, 3), dtype=float32)
tf.Tensor([[3. 3. 3.]], shape=(1, 3), dtype=float32
tf.Tensor([[4. 4. 4.]], shape=(1, 3), dtype=float32)
tf.Tensor([[-2. -2. -2.]], shape=(1, 3), dtype=float32)
tf.Tensor([[3. 3. 3.]], shape=(1, 3), dtype=float32)
tf.Tensor([[3. 3. 3.]], shape=(1, 3), dtype=float32)
計算某個張量的平方
tf.square (張量名)
計算某個張量的n次方
tf.pow (張量名, n次方數)
計算某個張量的開方
tf.sqrt (張量名)
a = tf.fill([1, 2], 3.) #[3,3]
print(a)
print(tf.pow(a, 3)) #三次方
print(tf.square(a)) #平方
print(tf.sqrt(a)) #開方
運行結果:
tf.Tensor([[3. 3.]], shape=(1, 2),dtype=float32)
tf.Tensor([[27. 27.]], shape=(1, 2),dtype=float32)
tf.Tensor([[9. 9.]], shape=(1, 2),dtype=float32)
tf.Tensor([[1.7320508 1.7320508]],shape=(1, 2), dtype=float32)
實現兩個矩陣的相乘
tf.matmul(矩陣1,矩陣2)
a = tf.ones([3, 2])#[ [1,1],[1,1],[1,1]]
b = tf.fill([2, 3], 3.) # [[3,3,3],[3,3,3]]
print(tf.matmul(a, b))
運行結果:
tf.Tensor(
[[6. 6. 6.]
[6. 6. 6.]
[6. 6. 6.]], shape=(3, 3), dtype=float32)
切分傳入張量的第一維度,生成輸入特征/標簽對,構建數據集
data = tf.data.Dataset.from_tensor_slices((輸入特征, 標簽))
features = tf.constant([12,23,10,17])
labels = tf.constant([0, 1, 1, 0])
dataset = tf.data.Dataset.from_tensor_slices((features, labels))
print(dataset)
for element in dataset:
print(element)
運行結果:
<TensorSliceDataset shapes: ((),()), types: (tf.int32, tf.int32))>
(<tf.Tensor: id=9, shape=(), dtype=int32, numpy=12>, <tf.Tensor: id=10, shape=(),dtype=int32, numpy=0>)
(<tf.Tensor: id=11, shape=(), dtype=int32, numpy=23>, <tf.Tensor: id=12, shape=(),dtype=int32, numpy=1>)
(<tf.Tensor: id=13, shape=(), dtype=int32, numpy=10>, <tf.Tensor: id=14, shape=(),dtype=int32, numpy=1>)
(<tf.Tensor: id=15, shape=(), dtype=int32, numpy=17>, <tf.Tensor: id=16, shape=(),dtype=int32, numpy=0>)
with結構記錄計算過程, gradient求出張量的梯度
with tf.GradientTape( ) as tape:
若干個計算過程
grad=tape.gradient(函數,對誰求導)
enumerate是python的內建函數,它可遍歷每個元素(如列表、元組或字符串), 組合為:索引 元素,
常在for循環中使用
enumerate(列表名)
seq = ['one', 'two', 'three']
for i, element in enumerate(seq):
print(i, element)
運行結果:
0 one
1 two
2 three
獨熱編碼(one-hot encoding):在分類問題中,常用獨熱碼做標簽,
標記類別: 1表示是, 0表示非。
tf.one_hot()函數將待轉換數據,轉換為one-hot形式的數據輸出。
tf.one_hot (待轉換數據, depth=幾分類)
classes = 3
labels = tf.constant([1,0,2]) # 輸入的元素值最小為0,最大為2
output = tf.one_hot( labels, depth=classes )
print(output)
運行結果:
[[0. 1. 0.]
[1. 0. 0.]
[0. 0. 1.]], shape=(3, 3), dtype=float32)
y = tf.constant ( [1.01, 2.01, -0.66] )
y_pro = tf.nn.softmax(y)
print("After softmax, y_pro is:", y_pro)
輸出結果:
After softmax, y_pro is: tf.Tensor([0.25598174 0.69583046
0.0481878], shape=(3,), dtype=float32)
賦值操作,更新參數的值并返回。
w.assign_sub (w要自減的內容)
調用assign_sub前,先用 tf.Variable 定義變量 w 為可訓練(可自更新)。
w = tf.Variable(4)
w.assign_sub(1)
print(w)
運行結果:
<tf.Variable 'Variable:0' shape=() dtype=int32, numpy=3>
返回張量沿指定維度最大值的索引
tf.argmax (張量名,axis=操作軸)
import numpy as np
test = np.array([[1, 2, 3], [2, 3, 4], [5, 4, 3], [8, 7, 2]])
print(test)
print( tf.argmax (test, axis=0)) # 返回每一列(經度)最大值的索引
print( tf.argmax (test, axis=1)) # 返回每一行(緯度)最大值的索引
運行結果:
[[1 2 3]
[2 3 4]
[5 4 3]
[8 7 2]]
tf.Tensor([3 3 1], shape=(3,), dtype=int64)
tf.Tensor([2 2 0 0], shape=(4,), dtype=int64)
iris神經網絡 分類項目
# -*- coding: UTF-8 -*-
# 利用鳶尾花數據集,實現前向傳播、反向傳播,可視化loss曲線
# 導入所需模塊
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) # 使用相同的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()標記參數可訓練
# 使用seed使每次生成的隨機數相同(方便教學,使大家結果都一致,在現實使用時不寫seed)
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 # 學習率為0.1
train_loss_results = [] # 將每輪的loss記錄在此列表中,為后續畫loss曲線提供數據
test_acc = [] # 將每輪的acc記錄在此列表中,為后續畫acc曲線提供數據
epoch = 500 # 循環500輪
loss_all = 0 # 每輪分4個step,loss_all記錄四個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: # with結構記錄梯度信息
y = tf.matmul(x_train, w1) + b1 # 神經網絡乘加運算
y = tf.nn.softmax(y) # 使輸出y符合概率分布(此操作后與獨熱碼同量級,可相減求loss)
y_ = tf.one_hot(y_train, depth=3) # 將標簽值轉換為獨熱碼格式,方便計算loss和accuracy
loss = 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_grad
w1.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為測試的總樣本數,將這兩個變量都初始化為0
total_correct, total_number = 0, 0
for x_test, y_test 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]
# 總的準確率等于total_correct/total_number
acc = total_correct / total_number
test_acc.append(acc)
print("Test_acc:", acc)
print("--------------------------")
# 繪制 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()