Day24 - 人工智慧 V.

斜槓學習 – 零基礎成為 AI 解夢大師秘笈

本文作者:Ovien

系列文章簡介

自由團隊將從0到1 手把手教各位讀者學會(1)Python基礎語法、(2)Python Web 網頁開發框架 – Django 、(3)Python網頁爬蟲 – 周易解夢網、(4)Tensorflow AI語言模型基礎與訓練 – LSTM、(5)實際部屬AI解夢模型到Web框架上。

學習資源

AI . FREE Team 讀者專屬福利 → Python Basics 免費學習資源

本篇教學將使用keras來實作上篇文章的題目

導入套件

%matplotlib inline
%config Inline
Backend.figure_format = 'retina'
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import seaborn as sns
import warnings

from datetime import datetime
from matplotlib.colors import ListedColormap
from sklearn.datasets import make_classification, make_moons, make_circlesfrom sklearn.metrics 
import confusion_matrix, classification_report, mean_squared_error, mean_absolute_error, r2_score
from sklearn.linear_model import LogisticRegression
from sklearn.utils import shuffle

from keras.models import Sequential
from keras.layers import Dense, Dropout, BatchNormalization, Activation
from keras.optimizers import Adam
from keras.utils.np_utils import to_categorical
import keras.backend as K
from keras.wrappers.scikit_learn import KerasClassifier

其實除了深度學習框架的model之外,其他套件都一樣,這意味著待會前處理與視覺化的部分都差不多。

資料集(Dataset)

def plot_data(X, y, figsize=None):  
    if not figsize:
        figsize = (8, 6)
    plt.figure(figsize=figsize)
    plt.plot(X[y==0, 0], X[y==0, 1], 'y*', alpha=0.5, label=0)
    plt.plot(X[y==1, 0], X[y==1, 1], 'g*', alpha=0.5, label=1)
    plt.xlim((min(X[:, 0])-0.1, max(X[:, 0])+0.1))
    plt.ylim((min(X[:, 1])-0.1, max(X[:, 1])+0.1))
    plt.legend()
    
    X, y = make_classification(n_samples=1000, n_features=2, n_redundant=0, 
                           n_informative=2, random_state=50, n_clusters_per_class=1)
plot_data(X, y)

Part 1. 使用同樣的資料集

找出線性切割線

lr = LogisticRegression()
lr.fit(X, y)
print('LR coefficients:', lr.coef_)
print('LR intercept:', lr.intercept_)

plot_data(X, y)

limits = np.array([-2, 2])
boundary = -(lr.coef_[0][0] * limits + lr.intercept_[0]) / lr.coef_[0][1]
plt.plot(limits, boundary, "r-", linewidth=2)
plt.show()

模型Model

model = Sequential()
model.add(Dense(units=1, input_shape=(2,), activation='sigmoid'))
model.summary()

輸出如下

Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_1 (Dense)              (None, 1)                 3         
=================================================================
Total params: 3
Trainable params: 3
Non-trainable params: 0
_________________________________________________________________

定義lossoptimizer

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

大家可以看到,這裡我們除了定義lossoptimizer,還有一個metrics,這個主要是在訓練過程中監看的指標

訓練Training

history =model.fit(x=X, y=y, verbose=1, epochs=25)

輸出

Epoch 1/30
32/32 [==============================] - 0s 572us/step - loss: 0.1842 - accuracy: 0.9630
Epoch 2/30
32/32 [==============================] - 0s 613us/step - loss: 0.1783 - accuracy: 0.9670
Epoch 3/30
32/32 [==============================] - 0s 574us/step - loss: 0.1728 - accuracy: 0.9670
.
.
.
Epoch 28/30
32/32 [==============================] - 0s 593us/step - loss: 0.1068 - accuracy: 0.9740
Epoch 29/30
32/32 [==============================] - 0s 595us/step - loss: 0.1055 - accuracy: 0.9740
Epoch 30/30
32/32 [==============================] - 0s 597us/step - loss: 0.1042 - accuracy: 0.9750

以上就是使用keras的訓練過程,從定義到訓練其實可以發現都比pytorch精簡很多,僅僅用了一行fit就把全部向前向後傳播做完了。再來看一下訓練完的history,一些功能性的 API 

pd.DataFrame(history.history)

這裡應該會到30,因為我們的epoch設成了30次,可以看到lossaccuracy會儲存在這個叫history的方法裡面,視覺化看一下預測的如何吧!

def plot_loss_accuracy(history):
    historydf = pd.DataFrame(history.history, index=history.epoch)
    plt.figure(figsize=(8, 6))
    historydf.plot(ylim=(0, max(1, historydf.values.max())))
    loss = history.history['loss'][-1]
    acc = history.history['accuracy'][-1]
    plt.title('Loss: %.3f, Accuracy: %.3f' % (loss, acc))
    
plot_loss_accuracy(history)

訓練的結果還不錯,loss往下、accuracy往上正是我們所樂見的

def plot_decision_boundary(func, X, y, figsize=(9, 6)):
    amin, bmin = X.min(axis=0) - 0.1
    amax, bmax = X.max(axis=0) + 0.1
    hticks = np.linspace(amin, amax, 101)
    vticks = np.linspace(bmin, bmax, 101)
    
    aa, bb = np.meshgrid(hticks, vticks)    
    ab = np.c_[aa.ravel(), bb.ravel()]    
    c = func(ab)    
    cc = c.reshape(aa.shape)    
    cm = plt.cm.RdBu
    cm_bright = ListedColormap(['#deff17', '#5be044'])
    
    fig, ax = plt.subplots(figsize=figsize)
    contour = plt.contourf(aa, bb, cc, cmap=cm, alpha=0.8)
    
    ax_c = fig.colorbar(contour)
    ax_c.set_label("$P(y = 1)$")
    ax_c.set_ticks([0, 0.25, 0.5, 0.75, 1])
    
    plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cm_bright)
    plt.xlim(amin, amax)
    plt.ylim(bmin, bmax)

plot_decision_boundary(lambda x: model.predict(x), X, y)

跟上一篇教學內容是一樣的結果,若有不熟悉的地方,請讀者們隨時回上篇文章複習喔!

y_pred = model.predict_classes(X, verbose=0)
print(classification_report(y, y_pred))

上面程式碼的輸出

              precision    recall  f1-score   support

           0       1.00      0.96      0.98       499
           1       0.96      1.00      0.98       501    
    accuracy                           0.98      1000   
   macro avg       0.98      0.98      0.98      1000
weighted avg       0.98      0.98      0.98      1000

月亮資料集

X, y = make_moons(n_samples=1000, noise=0.05, random_state=0)
plot_data(X, y)

建立一個一層的網路來檢視預測能力

model = Sequential()
model.add(Dense(1, input_shape=(2,), activation='sigmoid'))

model.compile('adam', 'binary_crossentropy', metrics=['accuracy'])
history = model.fit(X, y, verbose=0, epochs=100)
plot_loss_accuracy(history)

成效並不佳,與之前pytorch的實作差不多,如下視覺化結果:

y_pred = model.predict_classes(X, verbose=0)
print(classification_report(y, y_pred))

上面程式碼的輸出

              precision    recall  f1-score   support

           0       0.79      0.82      0.80       500
           1       0.81      0.78      0.80       500
    accuracy                           0.80      1000   
   macro avg       0.80      0.80      0.80      1000
weighted avg       0.80      0.80      0.80      1000

加深模型 (增加兩層)

model = Sequential()
model.add(Dense(4, input_shape=(2,), activation='tanh'))
model.add(Dense(2, activation='tanh'))
model.add(Dense(1, activation='sigmoid'))

model.compile(Adam(lr=0.01), 'binary_crossentropy', metrics=['accuracy'])
history = model.fit(X, y, verbose=0, epochs=100)

plot_loss_accuracy(history)

視覺化

plot_decision_boundary(lambda x: model.predict(x), X, y)

y_pred = model.predict_classes(X, verbose=0)
print(classification_report(y, y_pred))

上面程式碼的輸出

              precision    recall  f1-score   support

           0       1.00      1.00      1.00       500
           1       1.00      1.00      1.00       500    accuracy                           1.00      1000   macro avg       1.00      1.00      1.00      1000weighted avg       1.00      1.00      1.00      1000

pytorch的模型一樣,相同的模型可以達到100%的預測結果。

Keras & Pytorch 比較

可以發現keras相對於pytorch來說相對簡單,但是方便的東西,伴隨的是很多東西要使用他的API,筆者認為這裡有利有弊,有些底層的模型套件若沒有提供,但是你又無法用其他方法取代時,就會相當頭痛;相對pytorch,使用自由,但是入門相對困難,以上簡易的分析上述兩個 AI 的開發框架,提供給讀者們參考!

想更深入認識 AI . FREE Team ?

自由團隊 官方網站:https://aifreeblog.herokuapp.com/
自由團隊 Github:https://github.com/AI-FREE-Team/
自由團隊 粉絲專頁:https://www.facebook.com/AI.Free.Team/
自由團隊 IG:https://www.instagram.com/aifreeteam/
自由團隊 Youtube:https://www.youtube.com/channel/UCjw6Kuw3kwM_il39NTBJVTg/

文章同步發布於:第十二屆 IT 挑戰賽部落格

(繼續閱讀下一篇教學...)