Max Coding blog

基礎TensorFlow1和2與機器學習

2021/08/27

心情抒發

了解基礎numpy、pandas、matplotlib後我們就要進入深度學習了,我在進行深度學習的訓練的時候有時是使用linux作業系統,因為我的mac M1在下載tensorflow的時候遇到很多問題,因為mac M1和之前intel版本的mac不太一樣,之前的intel版本是x86架構的,但是mac M1是arm架構的,我花了三天還是沒辦法在我的mac上下載tensorflow,因此我在做機器學習時有兩種做法,第一種是使用google的Colaboratory,另一種是使用linux,所以我幫我的ASUS灌雙系統,為何不直接用windows10呢?因為我比較喜歡mac,所以我有時會在mac上寫程式,再透過ssh的方式在linux上進行,在這裡不得不讚嘆mac的界面設計,光看到就很舒服,而linux的界面有點太舊了,看了有點不習慣,那廢話不多說就進入我們的Machine Learning。 ## Linear Regression(線性回歸)design 所謂的線性回歸就是在觀察和歸納樣本的過程中向量和函數值呈現線性的關係,那這種關係可以用一個關係式來表達: Formula: Y = X1*W1 + X2*W2 + B 其中W和X都是矩陣,代表我們的參數可以不只一個,W代表Weights(權重),B代表Bias(偏移量)。 而運用這個公式有一個缺點,就是它的數值會介於正無限大到負無限大,所以這時候會加入活化函數,這個我稍後再提。

然而我們在進行機器學習有一個很重要的目標,就是讓Loss變小,什麼是Loss呢?我來粗略的介紹一下,在解釋前先看看這兩個關係式: 1. MSE(Mean-Square Error) 2. MAE(Mean-Absolute Error)

我們在做機器學習的時候希望計算機幫我們做預測的時候誤差值越低越好,總不能我們叫它預測一個一次函數,結果它算出來的答案是三次函數吧,所以Loss是在計算電腦在進行運算時的誤差值,我們稱之為loss function,loss function有很多種,而我目前只略懂這兩種。

首先來說MSE(Mean-Square Error),MSE顧名思義,均方誤差(MSE)計算的是預測值和實際觀測值間差的平方的均值。它只考慮誤差的平均大小,不考慮其向量,前面有提到y = f(x) = wx+b,這個y是我們預測的值,而我們要減去真實數據,即可得到差值,但為何要平方?因為我們的差值有可能是負的,怕會到時相消,所以這裡將它平方,可以保證為正值,但MSE方法仍然有個小問題,在「單位的解釋」上我們有點難以解釋數據,例如身高的平方的意義是?此時我們會使用RMSE(Root Mean Squared Error)將它開根號。

接著來說MAE(Mean-Absolute Error),其實MAE和MSE觀念很像,那觀念一樣的地方我就不多做贅述,MAE和MSE的關係上只差在一個是平方,另一個則是取絕對值,既然如此為何要分這兩種呢?老實說我也不太能理解,我在網路上看資料的時候他是這樣說的,「會有「在等於0時」不可微分的問題,不可微分會有什麼問題? 簡單來說,我們會沒辦法透過微分決定ML模型的修正方向。」對於微分我不是很理解,因為正在寫此篇的我還是小高一,但也無妨,實際上在做微分這運算的不是我,而是計算機,所以我也不用太著急,但MAE完全不能使用嗎? 倒也不完全是不能用,它也是有他的優勢的,那優勢在哪,有機會再來說吧!

處理機器學習的三大步驟

在進行ML的時候常常會因為其中的一個步驟做的不好而導致訓練失敗,所以每個環節都是非常重要的。 首先第一個步驟是設定一個未知的函式,就如同Linear regression那邊一樣,設定一個函式,再把參數加進去,算出y。 第二步,定義loss function,就如同前面所說的,後續會深入介紹。 第三步,optimization,這個步驟是很容易被遺忘的,而這個會在後面的例子中說到。 ## nonlinear regression(非線性函數) 前面有提到活化函式,這個活化函式是用在線性回歸之後,這邊我使用sigmoid()函式做介紹,故公式會變成下面那個: Formula: Y = Sigmoid(X1*W1 + X2*W2 + B) sigmoid()是一個非線性函數,它的作用是在於使整個輸出保持在0~1之間。 ## 函數數值訓練 ### 首先先看個code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import tensorflow.compat.v1 as tf
import numpy as np
import matplotlib.pyplot as plt

tf.disable_v2_behavior()

x = np.random.rand(200).astype(np.float32)
y = x*0.5+0.8
plt.plot(x,y,color = 'red')
weights = tf.Variable(tf.random.uniform([1],-1.0,1.0))
biases = tf.Variable(tf.zeros([1]))

func = weights*x + biases

loss = tf.reduce_mean(tf.square(func - y)) # MSE

optimization = tf.train.GradientDescentOptimizer(0.5)
train = optimization.minimize(loss)

init = tf.global_variables_initializer()

sess = tf.Session()
sess.run(init)

for i in range(201):
sess.run(train)
if i % 10 == 0:
plt.scatter(x,x*sess.run(weights)+sess.run(biases))
print(i,sess.run(weights),sess.run(biases))
plt.show()
### output : 0 [0.96190155] [0.7515451] 10 [0.69052416] [0.6988468] 20 [0.5954242] [0.7493372] 30 [0.5477933] [0.7746255] 40 [0.5239374] [0.7872911] 50 [0.5119891] [0.7936347] 60 [0.50600475] [0.79681194] 70 [0.50300753] [0.79840326] 80 [0.50150627] [0.7992003] 90 [0.5007544] [0.79959947] 100 [0.5003779] [0.7997994] 110 [0.50018924] [0.7998995] 120 [0.5000948] [0.7999497] 130 [0.50004745] [0.7999748] 140 [0.5000238] [0.7999874] 150 [0.50001186] [0.7999937] 160 [0.50000596] [0.79999685] 170 [0.50000304] [0.7999984] 180 [0.50000155] [0.7999992] 190 [0.5000008] [0.7999996] 200 [0.5000004] [0.7999998] 注意:此輸出不是固定的!由於我們是設計這個程式讓計算機去學習,所以它每次的學習效果都不一樣,因此它每次的輸出會不一樣。

接著來看函式圖形:

其中紅色那條線是我們正確的直線。 在這個圖面中可以看出電腦一開始的誤差很大,由藍色那條線可以知道,但經過200次的學習後可以使誤差變得非常小,趨近於我們正確的直線方程式:f(x) = y = 0.5*x + 0.8,這個現象也可以從輸出資料中看到這個現象。 接著來了解程式碼,這邊介紹程式碼不會講到各個函式的細節,若要看細節請去我另一篇筆記:tensorflow,這篇會傾向實作神經網路,所以基礎要先打好再來看這篇。 ### code introduction 一開始我們先import套件,由於我是自學機器學習,而tensorflow2.x有點太新,所以網路上可以學習的資源比較少,這邊才引用tensorflow 1.x版本,接著import numpy方便生成數據,然後import matplotlib.pyplot,此套件是方便進行數據可視化。 雖然我們已經import tensorflow 1.x版本,但是還是有可能和tensorflow2.x版本撞到,所以加入tf.disable_v2_behavior()來避免這個問題。 引用完套件後就來生成資料,首先運用numpy的生成亂數,由於在tensorflow在運算的時候大多是利用float32,所以我們這邊設定生成的變數也要是float32,由於要生成一個直線,所以要有一個直線方程式,所以我們這邊上一個方程式叫做f(x) = y = 0.5*x + 0.8,而當我們把大量的x帶入後畫成直線即是我們要的函式圖形,而我們這次的目標是訓練計算機能預測我們的weight和bias,以達到和我們的直線最相近的值,接著我們用Variable宣告我們的weight和bias,接著將weight和bias帶入直線方程式,func = weights*x + biases,在前面有說過我們希望我們訓練的值和實際的值的差距能越小越好,所以我們使用loss函式來計算訓練的值和實際的值的差距,這邊使用的方式是MSE,前面說過MSE這邊就不多贅述了。 做完loss function後就可以進行我們的optimization,由於我不會手刻神經網路,所以這邊直接使用函式,而這邊要做的optimization是使用梯度下降(GradientDescent),那什麼是梯度下降這個議題有機會我會在後面提到,所以這邊就直接引用,而他的參數我只放一個,這個參數代表他的learning_rate,而learning_rate越高或越低會造成什麼狀況我還不太明白,所以這邊就直接選擇中間值0.5來做優化。接著為了讓我們的loss變小,所以我們要進行優化減小,這裡引用minimize()來減小。 接著為了使用Variable,我們必須初始化所有Variable,接著用Session去跑,最後讓迴圈去跑,看使用者希望執行幾次,我這邊設定200次,然後每隔十次讓他輸出資料和圖形,這邊使用plt.scatter()顯示出點,最後plt.show()讓他顯示,我們就完成我們的函數數值訓練了! ## 建造一個神經網路(create a neural network) ### 首先先看code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import tensorflow.compat.v1 as tf
import numpy as np
import matplotlib.pyplot as plt
tf.disable_v2_behavior()

def add_layer(inputs,input_size,output_size,activation_function = None):
weight = tf.Variable(tf.random_normal([input_size,output_size]))
bias = tf.Variable(tf.zeros([1,output_size])+0.1)
y0 = tf.matmul(inputs,weight) + bias
if activation_function is None:
output = y0
else:
output = activation_function(y0)
return output

x = np.linspace(-1,1,300)[:,np.newaxis]
noise = np.random.normal(0,0.05,x.shape)
y = np.square(x) - 0.5 + noise

x_data = tf.placeholder(tf.float32,[None,1])
y_data = tf.placeholder(tf.float32,[None,1])

layer1 = add_layer(x_data,1,10,activation_function = tf.nn.relu)
predict = add_layer(layer1,10,1,activation_function = None)

loss = tf.reduce_mean(tf.reduce_sum(tf.square(y_data-predict),reduction_indices = [1]))
trainning = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
sess = tf.Session()
sess.run(tf.global_variables_initializer())

fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.scatter(x,y)
plt.ion()
plt.show()

for i in range(1000):
sess.run(trainning,feed_dict = {x_data:x,y_data:y})
if i % 50 == 0:
print(sess.run(loss,feed_dict = {x_data:x,y_data:y}))
try:
ax.lines.remove(lines[0])
except Exception:
pass
predict_val = sess.run(predict,feed_dict = {x_data:x})
lines = ax.plot(x,predict_val,'r-',lw = 5)
plt.pause(0.1)
### output: 0.29719043 0.008188563 0.005622979 0.0047432035 0.0042990027 0.0040122583 0.0038019188 0.003706917 0.0035503162 0.00343985 0.003398858 0.003354532 0.0033004875 0.0032468617 0.0032003152 0.0031578606 0.0031319312 0.0031033608 0.003071908 0.0030463308 ### 函數圖形

神經網路

我們基本的神經網路構造是由三種層組合而成的,分別為input layer、hidden layer、output layer,我在這邊設定我們的hidden layer有10個。 ### code introduction 首先要定義一個神經層,名稱叫做add_layer(),要傳入的參數有4個,為了滿足函數關係,我們的函數式為:y = wx+b,第一個參數是我們的x,第二個參數是我們神經元的輸入層數量,第三個參數是我們神經元輸出層數量,第四個是我們要加入的激勵函數,常見的激勵函數有:sigmoid、tanh、ReLU,負責做非線性的調整,使我們的神經元在某個部位較為特別。 接著定義我們weight和bias,我們的weight是給予亂數,而bias是給予0.1,接著算出我們的y,所以我們的y = wx+b的所有數字都齊全了,接著將他傳入激勵函數,所以要先判斷使用者是否有給予激勵函數,如果沒有,則使用預設值None,使用原本的線性函數,而如果有給予激勵函數,則會將y傳入激勵函數,最後再將結果回傳。

由於要訓練電腦做出最佳的判斷,我們必須先有一個函數式,將x輸入可得到y,而我們y不見得是完全落在我們函式圖形上,應該會有偏差,所以我們這邊加入noise,使數據有些偏差,這樣會更像真實數據。 接著建造兩個placeholder,一個是x_data另一個是y_data,而x_data是代表我們一開始生成的x,y_data是代表我們實際數據的y,將此placeholder加入我們的add_layer(),由於我們隱藏層有10個所以輸入10,且我希望我的x_data可以運用激勵函數數值縮減到0~1之間,所以這邊使用ReLU,簡單說一下ReLU是什麼ReLU是一種激勵函數,能讓原本大於1的數變成縮到0~1之間,而小於0的數自動變成0。

接著寫出loss function,這邊使用的方法是MSE,這邊比較不一樣的是reduce_sum()裡的reduction_indices是指說我們希望對哪一個維度做加總,默認值是把所有數據做加總也就是一維,而如果給予的參數是0代表是對第0維的位置做加總,以此類推。 再來是要做optimization,這裡是用的方法是Gradient Descent(梯度下降),接著將結果的loss盡可能取較小的,所以取minimize()。

由於我們希望能有數據可視化的效果,所以這邊先利用plt.figure()建立一個新的圖形,接著使用fig.add_subplot()來建造一個子圖,接著將我們實際的點用scatter()畫出散佈圖,再來用迴圈去跑,由於我不希望將所有的線條都畫出來,所以我要將前一份刪除,但在第一份資料顯示的時候沒有前一份,此時會出現error,所以這裡使用try語句,如果出現error就pass,如果沒有就將它刪除。 最後用sess.run()來跑tranning,並分別給予x_data和y_data值,同時等候0.1秒輸出一個圖,並每隔50次輸出一次結果,而我們可以看到數值下降的趨向,以及函數圖的紅色曲線越來越接近我們的真實值,代表電腦已經經過訓練了,我們的結果也完成了。 ## 存取已訓練好的資料 ### 程式碼 #### 儲存:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import tensorflow.compat.v1 as tf

tf.disable_v2_behavior()

w = tf.Variable([[1,2,3],[4,5,6]], dtype = tf.float32, name = 'weight')
b = tf.Variable([[1,2,3]], dtype = tf.float32, name = 'bias')

init = tf.global_variables_initializer()

saver = tf.train.Saver()

with tf.Session as sess:
sess.run(init)
save_path = saver.save(sess, 'my_net/save_net.ckpt')
print('Save path: ', save_path)
#### 提取:
1
2
3
4
5
6
7
8
9
10
11
12
13
import tensorflow.compat.v1 as tf
import numpy as np

tf.disable_v2_behavior()

w = tf.Variable(np.arange(6).reshape((2, 3)),dtype = tf.float32, name = 'weight')
b = tf.Variable(np.arange(3).reshape((1,3)), dtype = tf.float32, name = 'bias')

saver = tf.train.Saver()
with tf.Session() as sess:
saver.restore(sess, 'my_net/save_net.ckpt')
print("weight: ", sess.run(w))
print('bias: ', sess.run(b))
在tensorflow1.x只提供變數的存取和提取,不提供存取整個神經網路,而這邊的程式十分易懂,所以這邊就不多做介紹了。 ## CNN ### 程式碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.optimizers import SGD
from tensorflow.keras.datasets import mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(60000, 28, 28, 1) / 255
x_test = x_test.reshape(10000, 28, 28, 1) / 255
y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)

model = Sequential()
model.add(Conv2D(16, (3,3), padding='same', input_shape=(28,28,1),activation = 'relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(32, (3,3), padding='same', activation = 'relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(64, (3,3), padding='same', activation = 'relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Flatten())
model.add(Dense(60, activation = 'relu'))
model.add(Dense(10, activation = 'softmax'))
model.summary()

model.compile(loss = 'mse', optimizer = SGD(lr=0.087), metrics = ['accuracy'])
model.fit(x_train, y_train, batch_size = 128, epochs = 12)
result = model.predict_classes(x_test)
# result = np.argmax(model.predict(x_test), axis = -1)
loss, acc = model.evaluate(x_test, y_test)
print(f'accuracy: {acc*100:.2f}%')

def my_predict(n):
print('CNN predict: ', result[n])
X = x_test[n].reshape(28,28)
plt.imshow(X, cmap='Greys')
n = 893
my_predict(n)
plt.show()
model.save('CNNmodel.h5')
### 輸出 ### 程式介紹 首先引入基本的套件,接著引入to_categorical,to_categorical的功用是將資料變成one-hot encoding,然後是Sequential,幫助我們建立神經網路,再來引入Keras寫好的神經層,我們會用到卷積層和池化層,以及會使用到fully connected,所以引入Dense,還有我們會將資料打平成向量,所以引入Flatten,在optimization的時候是使用SGD,最後我們會運用到MNIST資料集。 我們將MNIST的資料讀取,分別把training data和testing data取出並存取,這裡的imshow()只是單純想要觀看MNIST的圖片,再來將我們x data做處理,由於我們的training data有60000份,testing data有10000份,且每張圖片都是28*28,所以這邊reshape,將資料變成784維的向量,然後我們784筆資料的值是0~255,我們偏向將資料值能在0~1之間,所以這邊我們除以255,再來是y data,我們將y data轉成one-hot encoding ,為10維的向量。 我們使用Sequential建造神經網路,使用add()函式增加神經層,Conv2D()是我們的卷積層,共三層卷積層,第一層卷積層我們設定16個filter,filter是我們每次進行篩選的時候會運用到的篩選器,而當我們有幾個filter就會有幾個channel第二個參數是擺入我們filter的大小,而padding代表我們是否要在我們的image外添加0,這裡選擇same,代表我們希望做完卷積層之後的大小和原圖一樣,至於添加幾層0,會由電腦自行計算,由於第一層卷積層不知道我們輸入的圖形樣式,所以這邊我們告訴它是28*28*1,記得channel數也要加,最後選擇我們的激勵函數,這邊選擇ReLU,其他卷積層的作法和此層相同,所以這邊就不多做贅述,再來介紹一下池化層,這裡是使用max pooling,我們的pooling大小設為2*2,所以我們會像filiter一樣進行掃描,在2*\2的範圍內找最大值,並做紀錄,此時我們的image會縮小。再來我們將此model進行flatten(),將資料全部打平成向量,並添加兩層Dense,來進行fully connected,這裡的model.summary()只是單純看神經網路的架構。再來使用compile來配置訓練model,我們的model使用MSE來計算loss function,優化器使用SGD,learning rate調整為0.09,而metrics這個參數是判斷訓練和測試時的成效。此處的fit()函數是我們訓練的模型,第一和二個參數是我們的數據,第三個是我們每次做批量訓練的數量,因為我們不可能直接將所有training data一次全部訓練,這樣數據量太大,所以要做batch training,epochs是我們要訓練幾次。用Keras做預測的時候有兩種方法,一種是使用predict(),這種回傳的是機率,另一種是predict_classes(),這種則會回傳向量中數值最大的index,如果使用predict()想要達到相同效果的話,需再加上argmax(),這邊就選擇使用predict_classes(),我們會這樣做是因為我們使用的是one-hot encoding ,所以得到index時即可找到預測的數值,再來使用model.evaluate()計算model的loss 和 accuracy,而最後那個函數是幫我們輸入編號並輸出預測數字已行實際圖片,完成以上後即完成此次實作。

ResNet50

程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from tensorflow.keras.applications import ResNet50
from tensorflow.keras.applications.resnet50 import preprocess_input
from tensorflow.keras.preprocessing.image import load_img, img_to_array
from urllib.request import urlretrieve

urlretrieve("https://raw.githubusercontent.com/yenlung/Deep-Learning-Basics/master/data/imagnet-classes.txt", "imagnet-classes.txt")

cooper=[]
for i in range(1,7):
urlretrieve(f"https://github.com/yenlung/Deep-Learning-Basics/raw/master/data/cooper/cooper0{i}.jpg", f"cooper0{i}.jpg")
cooper.append(f"cooper0{i}.jpg")
img = load_img(cooper[2], target_size = (224,224))
x = img_to_array(img)
plt.axis('off')
plt.imshow(x/255)
resnet = ResNet50()
with open('imagnet-classes.txt') as f:
labels = [line.strip() for line in f.readlines()]
x = x.reshape(1, 224, 224, 3)
inp = preprocess_input(x)
[k] = np.argmax(resnet.predict(inp), axis=-1)
print(f"ResNet 覺得是 {labels[k]}")
plt.show()

影像辨識

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from urllib.request import urlretrieve
import pickle
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.applications.resnet50 import preprocess_input
from tensorflow.keras.applications import ResNet50V2
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

urlretrieve("https://github.com/yenlung/Deep-Learning-Basics/raw/master/data/myna/myna_input.pickle", "myna_input.pickle")
urlretrieve("https://github.com/yenlung/Deep-Learning-Basics/raw/master/data/myna/myna_output.pickle", "myna_output.pickle")
file = open('myna_input.pickle', 'rb')
data = pickle.load(file)
file.close()
file = open('myna_output.pickle', 'rb')
target = pickle.load(file)
file.close()

n=1
plt.axis('off')
plt.imshow(data[n])

x_train = preprocess_input(data)
plt.axis('off')
plt.imshow(x_train[n])

y_train = to_categorical(target-1, 3)
y_train[n]

resnet = ResNet50V2(include_top=False, pooling="avg")
resnet.trainable = False

model = Sequential()
model.add(resnet)
model.add(Dense(3, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()
model.fit(x_train, y_train, batch_size=9, epochs=25)

y_predict = np.argmax(model.predict(x_train), -1)
labels=["白尾八哥", "家八哥", "(土)八哥"]

def classify_image(inp):
inp = inp.reshape((-1, 256, 256, 3))
inp = preprocess_input(inp)
prediction = model.predict(inp).flatten()
return {labels[i]: float(prediction[i]) for i in range(3)}

image = gr.inputs.Image(shape=(256, 256), label="八哥照片")
label = gr.outputs.Label(num_top_classes=3, label="AI辨識結果")

RNN(情意分析)

程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from tensorflow.keras.preprocessing import sequence
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Embedding
from tensorflow.keras.layers import LSTM
from tensorflow.keras.datasets import imdb
from tensorflow.keras.datasets.imdb import get_word_index

(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=10000)
x_train = sequence.pad_sequences(x_train, maxlen=100)
x_test = sequence.pad_sequences(x_test, maxlen=100)

model = Sequential()
model.add(Embedding(10000, 128))
model.add(LSTM(128))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()

model.fit(x_train, y_train, batch_size=32, epochs=10, validation_data=(x_test, y_test))

word_index = get_word_index()
print(word_index['this'])

text = "this movie is bad"
seq = [word_index[x] for x in text.split()]
print(model.predict([seq]))

text = "this movie is good"
seq = [word_index[i] for i in text.split()]
print(model.predict([seq]))

model_json = model.to_json()
open('imdb_model_architecture.json', 'w').write(model_json)
model.save_weights('ismdb_model_weights.h5')

程式碼介紹

首先引入基本套件,再來引入sequence套件,這個套件是對我們的文字做處理的,再來是Sequential,這個就是架設神經網路的框架,然後引入Dense做全連結的神經網路,這邊比較特別的是Embedding,這個是Keras很貼心的地方,這個神經層是負責降維度,再來到了RNN的重頭戲,LSTM(Long Short-Term Momory)是RNN的一種,其實還有另一種叫做GRU,這邊不會解釋LSTM,因為LSTM非常複雜,反正這邊就把它當作一種RNN的神經層,然後我們引入imdb,這個是網路電影資料庫,我們要從裡面提取資料,最後是get_word_index,這個是imdb裡支援的,它可以給我們得到單字的index。 再來要取得數據,我們從imdb裡提取,我們只提取10000個數字,太多數字數據會太大,然後將此向量做分割,100個數字算一組,如果未滿100個數字就補0。 再來建造神經網路和訓練與往常一樣,這邊就不多贅述了,只是這邊要注意,用colaby做的時候要開gpu,或者盡量使用有gpu運算的電腦,不然會訓練非常久。 然後我們來看看'this'這個字的index是多少,輸出時可以知道是11,然後我們輸入一個對電影的評價,並將每個字做分割並傳入做預測,此時得到的數字越大代表電腦判斷這句話是正向的,越接近0時代表這句話是反面的,最後再做儲存就完成這次的實作了。 ## Tokenizer ### 程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from tensorflow.keras.preprocessing.text import Tokenizer
from urllib.request import urlretrieve
import pickle

urlretrieve("https://github.com/yenlung/Deep-Learning-Basics/raw/master/data/dream.txt", "dream.txt")
f = open('dream.txt', 'r')
lines = f.readlines()
f.close()
text_lines = [x.lstrip('\u3000\u3000') for x in lines]
text = ''.join(text_lines)
tokenizer = Tokenizer(char_level=True)
tokenizer.fit_on_texts([text])
print(tokenizer.texts_to_sequences(["人生短暫,珍惜當下"]))
print(tokenizer.sequences_to_texts([[12, 131, 804, 792, 1, 261, 403, 203, 59]]))
f = open('MyTokenizer.pkl', 'wb')
pickle.dump(tokenizer, f)
f.close()

# 開啟檔案方式:
# f = open('tokenizer.pkl', 'rb')
# tokenizer = pickle.load(f)
# f.close()
### 輸出 [[12, 131, 804, 792, 1, 261, 403, 203, 59]] ['人 生 短 暫 , 珍 惜 當 下'] ### 程式碼介紹 這邊只會稍微講解一下,這邊引入套件的部分有一個是我們的主題,就是Keras底下的Tokenizer。 我們先從蔡炎龍教授的github下載紅樓夢,並將紅樓夢逐一讀行存進lines裡,各位可以將其中一句輸出,會看到000000這個亂碼,所以我們要用lstrip()進行刪除,這裡會用迭代將每一行都移除此符號,再來用join將全部串起來,在join前面的空字串代表串起來的中間不要加字元,再來建造我們的tokenizer,裡面的參數char_level如果是True代表我們要每一個字都進行理解,反之則否,再來進行tokenizer的訓練,訓練完後我們將字串轉成數值,跟將數值轉成字串,即可得到我們的結果。

by 中和高中 吳振榮
CATALOG
  1. 1. 心情抒發
  2. 2. 處理機器學習的三大步驟
    1. 2.1. 接著來看函式圖形:
    2. 2.2. 神經網路
  3. 3. ResNet50
    1. 3.1. 程式碼
  4. 4. 影像辨識
  5. 5. RNN(情意分析)
    1. 5.1. 程式碼
    2. 5.2. 程式碼介紹
      1. 5.2.0.1. by 中和高中 吳振榮