動機:因應近來 TensorFlow 釋出 2.0,想要運用 [TensorFlow 2.0 + Keras] 來構建 CNN 深度學習網路,並輸入 Fashion MNIST 公開資料集來做 圖片分類(Image Classification),要如何做呢?!
準備環境:
1.OS: Ubuntu 18.04.3 LTS
2.GPU: GeForce GTX 1080 x 2
3.CUDA: 10.1
4.Python 3.7.4
5.Jupyter-notebook 6.0.1
操作步驟:
全程使用 Jupyter-Notebook 操作畫面(第七版),請參閱連結網頁... http://dmfamily.ddns.net:8000/classification7.html
程式分享於... https://github.com/dvsseed/tf2_keras_cnn_jupyter/blob/master/classification7.ipynb
另外,筆者將上述網頁內容(第四版, 內容不完整)摘錄至本文尾...⤓
心得:
1.本次操作係以 [Dataset ⇒ Model ⇒ Analysis] 三階段製作,使用 Jupter Notebook 來直觀程式語法及執行結果,十分方便自學及教學,感謝背後許多辛苦付出的人士!!
2.有關『三階段』,可以區分:問題、方法、結論(結果)
2.1.問題:實際的問題為何?!
2.2.方法:示意圖、指令 (加註解),目的為何?!
2.3.結論:說明清楚並呼應問題
2.4.圖要前後一致,指令要正確、版本一致
3.有關『三階段』,可以區分:Dataset、Model、Analysis
3.1.Dataset:要有基本描述、資料探索、資料屬性、秀圖(指令→結果)...
3.2.Model:建立模型(有幾層)、參數標註清楚、如何調整(指令)、效果如何...
3.3.Analysis:分析Result、觀察優、缺點(指令)
3.4.流程圖、圖(視覺化)
4.有關 Blogger 無法秀出 PDF內容及嵌入 HTML程式碼內容,雖本文 tf2.0 程式已多次改版,但筆者已賴得做 html tag 轉換,故 文尾網頁內容 未適時更新,特向各位讀者致歉!!
p.s. 有關本次教學檔案(三個程式檔),筆者分享於 https://github.com/dvsseed/tf2_keras_cnn_jupyter
參攷:
1. TensorFlow, https://www.tensorflow.org/
2. Keras, https://keras.io/
3. Python, https://www.python.org/
4. Jupyter Notebook, https://jupyter.org/
X X X X X
準備環境:
1.OS: Ubuntu 18.04.3 LTS
2.GPU: GeForce GTX 1080 x 2
3.CUDA: 10.1
4.Python 3.7.4
5.Jupyter-notebook 6.0.1
操作步驟:
全程使用 Jupyter-Notebook 操作畫面(第七版),請參閱連結網頁... http://dmfamily.ddns.net:8000/classification7.html
程式分享於... https://github.com/dvsseed/tf2_keras_cnn_jupyter/blob/master/classification7.ipynb
另外,筆者將上述網頁內容(第四版, 內容不完整)摘錄至本文尾...⤓
心得:
1.本次操作係以 [Dataset ⇒ Model ⇒ Analysis] 三階段製作,使用 Jupter Notebook 來直觀程式語法及執行結果,十分方便自學及教學,感謝背後許多辛苦付出的人士!!
2.有關『三階段』,可以區分:問題、方法、結論(結果)
2.1.問題:實際的問題為何?!
2.2.方法:示意圖、指令 (加註解),目的為何?!
2.3.結論:說明清楚並呼應問題
2.4.圖要前後一致,指令要正確、版本一致
3.有關『三階段』,可以區分:Dataset、Model、Analysis
3.1.Dataset:要有基本描述、資料探索、資料屬性、秀圖(指令→結果)...
3.2.Model:建立模型(有幾層)、參數標註清楚、如何調整(指令)、效果如何...
3.3.Analysis:分析Result、觀察優、缺點(指令)
3.4.流程圖、圖(視覺化)
4.有關 Blogger 無法秀出 PDF內容及嵌入 HTML程式碼內容,雖本文 tf2.0 程式已多次改版,但筆者已賴得做 html tag 轉換,故 文尾網頁內容 未適時更新,特向各位讀者致歉!!
p.s. 有關本次教學檔案(三個程式檔),筆者分享於 https://github.com/dvsseed/tf2_keras_cnn_jupyter
參攷:
1. TensorFlow, https://www.tensorflow.org/
2. Keras, https://keras.io/
3. Python, https://www.python.org/
4. Jupyter Notebook, https://jupyter.org/
X X X X X
Image Classification: Fashion MNIST with TensorFlow 2 + Keras and Deep Learning -- CNN(Convolutional Neural Network)¶
In all transformer functions you can specify row_axis, col_axis and channel_axis according to the array of images you pass into the function.
Note that shearing is different from just rotation since it deforms the given image by multiplying it with the following transformation matrix
When we start the ImageDataGenerator it runs in an endless loop. But since we just want a few example we let it run in a for loop and break out of it when we have collected enough examples.
This allows us to create 100 images from just one image.
Most of deep learning consists of chaining together simple layers. Most layers, such as
默認情況下,
和 (保存在 "HDF5" 附檔名為 .h5 保存並序列化模型)
這可以導出模型,以便在不訪問原始 python 代碼的情況下使用它。
而且可以通過恢復優化器狀態的方式,從中斷的位置恢復訓練。
保存完整模型會非常有用—可以在 TensorFlow.js (HDF5, Saved Model) 加載它們,然後在 web 瀏覽器中訓練和運行它們,
或者使用 TensorFlow Lite 將它們轉換為在移動設備上運行(HDF5, Saved Model)
The TensorFlow 2.0.0 Tutorials and Courses by Davis on 2019-10-30¶
Ref: https://www.tensorflow.org/tutorials/keras/classification¶
In [ ]:
# 檢查 python version
!python3 -V
In [1]:
# 更新 The Python Package Installer — pip
# !pip3 install --user --upgrade pip
# !pip3 install --user -U tensorflow-gpu
# !pip3 install --user -U matplotlib
# !pip3 install --user -U jupyter
# !pip3 install --user -U numpy
!pip3 -V
Outline¶
載入 python packages¶
In [2]:
from __future__ import (absolute_import, division, print_function, unicode_literals) # 參攷[1]
# TensorFlow and tf.keras
import tensorflow as tf # 參攷[2]
from tensorflow import keras # 參攷[3]
print(tf.__version__) # 查詢 TensorFlow版本
print(tf.version.VERSION)
print(keras.__version__) # 查詢 keras 版本
# Helper libraries
import numpy as np # 陣列運算的數學函數函式庫, 參攷[4]
import matplotlib.pyplot as plt # 繪圖庫, 參攷[5]
import Ipynb_importer # 參攷[6]
import tf2tools
# 將matplotlib的圖表直接嵌入到Notebook之中, 參攷[7]
%matplotlib inline
參攷:¶
- https://python-future.org/quickstart.html
- https://www.tensorflow.org/
- https://www.tensorflow.org/guide/keras
- https://numpy.org/
- https://matplotlib.org/3.1.1/tutorials/introductory/pyplot.html
- https://jupyter-notebook.readthedocs.io/en/latest/examples/Notebook/Importing%20Notebooks.html
- https://www.tutorialspoint.com/jupyter/jupyter_notebook_plotting.htm
Input | Process | Output |
---|---|---|
'T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot' | [ ] | class_names |
In [3]:
# 利用 List(串列), 建立 10 種類別, 參攷
class_names = ['T-shirt/top', # 0: index
'Trouser', # 1
'Pullover', # 2
'Dress', # 3
'Coat', # 4
'Sandal', # 5
'Shirt', # 6
'Sneaker', # 7
'Bag', # 8
'Ankle boot'] # 9
Input | Process | Output |
---|---|---|
class_names | print(len( )) | 10 |
In [4]:
# 列出類別總數
print(len(class_names))
Input | Process | Output |
---|---|---|
9 | class_names[ ] | 'Ankle boot' |
In [5]:
# 列出第 10 個(輸入: 數字), index 從 0 起算
class_names[9]
Out[5]:
In [6]:
# 使用 "關鍵字" 來搜尋
keyword = 'Ankle boot'
# using filter()
# to find indices
res_list = list(filter(lambda x: class_names[x] == keyword, range(len(class_names)))) # 參攷
# printing resultant
print("[" + keyword + "] is " + str(res_list[0]))
Input | Process | Output |
---|---|---|
class_names | ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot'] |
In [7]:
# 列出所有類別名稱
class_names
Out[7]:
Input | Process | Output |
---|---|---|
fashion_mnist | .load_data() | (train_images, train_labels), (test_images, test_labels) |
In [8]:
# 下載 Fashion-MNIST dataset
fashion_mnist = keras.datasets.fashion_mnist
# 載入 Fashion-MNIST
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
- 提取資料(Extract):將資料從容器(硬碟、雲端等)提取
- 轉換資料(Transform):將資料轉換為模型可讀取的資料,同時進行數據清理等預處理
- 裝載資料(Load):將處理好的資料裝載至加速器(GPU)
In [9]:
# 秀出 Fashion-MNIST 檔案下載的位置
!ls ~/.keras/datasets/fashion-mnist/*ubyte.gz
#!dir %userprofile%\.keras\datasets\fashion-mnist # for windows
參攷: https://support.anaconda.com/hc/en-us/articles/360023858254-Executing-Terminal-Commands-in-Jupyter-Notebooks¶
- train-images-idx3-ubyte.gz 60,000 張訓練集圖片
- train-labels-idx1-ubyte.gz 60,000 張訓練集圖片對應的標籤
- t10k-images-idx3-ubyte.gz 10,000 張測試集圖片
- t10k-labels-idx1-ubyte.gz 10,000 張測試集圖片對應的標籤
讀取(open)訓練集圖像檔案 | ⇒ |
[:4] magic number [4:8] number of images [8:12] number of rows [12:16] number of columns |
⇒ |
擷取第1張圖片的像素 [16: 16+784] pixel |
⇒ |
利用numpy和cv2轉換格式 並保存(cv2.imwrite)成.jpg格式的圖片 |
In [10]:
# 以訓練集圖像文件 train-images-idx3-ubyte 為例
# 使用open()函數打開文件,並使用read()方法將所有的文件數據讀入到一個字串中
with open('/home/d1075102/.keras/datasets/fashion-mnist/train-images-idx3-ubyte', 'rb') as f:
trfile = f.read() # file是str類型,其中的每個元素是存儲的1個byte的內容
magic_number = trfile[:4] # 查看前4個bytes,即magic number的內容,是否是2051
print(magic_number) # Binary
print(magic_number.hex()) # Hexadecimal, hex
print(int(magic_number.hex(), 16)) # 轉 Decimal, dec
print() ##
num_images = int(trfile[4:8].hex(), 16) # 查看圖像數量
print('Number of images: {}'.format(num_images)) # 參攷[1]
h_image = int(trfile[8:12].hex(), 16) # 圖像高度
print('Height of image: {}'.format(h_image))
w_image = int(trfile[12:16].hex(), 16) # 圖像寬度
print('Width of image: {}'.format(w_image))
print() ##
# 擷取第1張圖片的像素
image1 = [item for item in trfile[16 : 16 + 784]]
print('Pixel of image: {}'.format(len(image1)))
import cv2
# 利用numpy和cv2轉換其格式,並保存成.jpg格式的圖片
image1_np = np.array(image1, dtype=np.uint8).reshape(28, 28, 1)
# 圖片大小: nH高×nW寬×nC通道數(channel), 彩色圖片的nC數為3(三原色RGB)、灰階圖片nC數則為1, 參攷[2]
print('Shape of image: {}'.format(image1_np.shape))
cv2.imwrite('image1.jpg', image1_np) # 參攷[3]
Out[10]:
In [ ]:
# 秀出 上述解壓後之圖片 image1.jpg
# import matplotlib.pyplot as plt # plt 用於顯示圖片
import matplotlib.image as mpimg # mpimg 用於讀取圖片, 參攷
boot = mpimg.imread('image1.jpg') # 讀取 .jpg 成為 numpy.ndarray
print(boot.shape) # (28, 28)
print(type(boot))
tf2tools.plot_image(boot)
Don't do this cell⇩
In [ ]:
''' ***請勿執行***請勿執行***請勿執行*** '''
# 將MNIST數據集保存成.jpg圖片格式: ubyte=>jpg
''' 將二進制格式的MNIST數據集轉成.jpg圖片格式並保存,圖片標籤包含在圖片檔名中 '''
import numpy as np
import cv2
import os
import codecs
def save_mnist_to_jpg(mnist_image_file, mnist_label_file, save_dir):
if 'train' in os.path.basename(mnist_image_file): # 參攷[1]
num_file = 60000
prefix = 'train'
else:
num_file = 10000
prefix = 'test'
with open(mnist_image_file, 'rb') as f1: # 參攷[2]
image_file = f1.read()
with open(mnist_label_file, 'rb') as f2:
label_file = f2.read()
image_file = image_file[16:]
label_file = label_file[8:]
for i in range(num_file):
label = label_file[i]
image_list = [item for item in image_file[i * 784 : i * 784 + 784]]
image_np = np.array(image_list, dtype=np.uint8).reshape(28, 28, 1)
save_name = os.path.join(save_dir, '{}_{}_{}.jpg'.format(prefix, i, label)) # 參攷[3]
cv2.imwrite(save_name, image_np)
print('{} ==> {}_{}_{}.jpg'.format(i, prefix, i, label))
train_image_file = '/home/d1075102/.keras/datasets/fashion-mnist/train-images-idx3-ubyte'
train_label_file = '/home/d1075102/.keras/datasets/fashion-mnist/train-labels-idx1-ubyte'
test_image_file = '/home/d1075102/.keras/datasets/fashion-mnist/t10k-images-idx3-ubyte'
test_label_file = '/home/d1075102/.keras/datasets/fashion-mnist/t10k-labels-idx1-ubyte'
save_train_dir = '/home/d1075102/.keras/datasets/fashion-mnist/train_images/'
save_test_dir ='/home/d1075102/.keras/datasets/fashion-mnist/test_images/'
if not os.path.exists(save_train_dir): # 參攷[4]
os.makedirs(save_train_dir)
if not os.path.exists(save_test_dir):
os.makedirs(save_test_dir)
save_mnist_to_jpg(train_image_file, train_label_file, save_train_dir)
save_mnist_to_jpg(test_image_file, test_label_file, save_test_dir)
Training set¶
- training set = 60,000 images
- each image represented as 28 x 28 pixels
Input | Process | Output |
---|---|---|
train_images.shape | print( ) | (60000, 28, 28) |
In [11]:
# 秀出 張量tensor: (張數, 圖高, 圖寬)
print(train_images.shape) # shape函數表示張量的形狀, 參攷[1]
print(train_images.dtype) # data type, 參攷[2]
Input | Process | Output |
---|---|---|
len(train_labels) | print( ) | 60000 |
In [12]:
# 秀出 資料量
print(len(train_labels)) # 參攷[1]
print(train_labels.size) # 參攷[2]
Input | Process | Output |
---|---|---|
train_labels | type( ) | numpy.ndarray |
In [13]:
# 秀出 屬性
type(train_labels)
# An array object represents a multidimensional, homogeneous array of fixed-size items.
# ndarray資料結構: 只容許一種資料類型,
# 如果同時儲存有數值,布林值,會被自動轉換為數值,
# 如果同時儲存有數值,布林值與文字,會被自動轉換為文字
Out[13]:
In [14]:
# 秀出 資料量
len(train_labels)
Out[14]:
In [15]:
# 秀出 label 內容, Each label is an integer between 0 and 9:
train_labels
Out[15]:
Test set¶
- test set = 10,000 images
- each image represented as 28 x 28 pixels
In [16]:
# 秀出 張量tensor: (張數, 圖高, 圖寬)
test_images.shape # shape函數表示張量的形狀
Out[16]:
In [17]:
# 秀出 資料量
len(test_labels)
Out[17]:
In [18]:
# 秀出 28x28 維的 灰階畫素位元值: 0-255
print(train_images[0])
In [19]:
# 秀出 第一張訓練圖像
img = train_images[0]
print(img.shape) # tensor: (圖高height, 圖寬width)
tf2tools.plot_image(img)
In [ ]:
# 畫一張全黑的圖片, 0代表著黑色,255代表白色
# np.zeros 產生給定維度 用0填充 的陣列(數組)
black_zeros_array = np.zeros((28, 28), dtype='float')
# print(black_zeros_array)
tf2tools.plot_image(black_zeros_array)
Preprocess the data¶
將 (上面的圖片畫素值 / 255):除 255 之後,本來 [0-255] 的值就會變成 [0-1],但數值的分佈比例還是一樣的,在機器學習中,通常用正規化,把值變成 [0-1],方便訓練及提高準確率
In [20]:
# normalizing
train_images = train_images / 255. # dtype=float64
test_images = test_images / 255.0
print(train_images.dtype)
In [21]:
train_images[0]
Out[21]:
In [22]:
# 秀出多張訓練集圖片(含label)
tf2tools.plot_images(train_images, train_labels)
In [ ]:
''' ***請勿執行***請勿執行***請勿執行*** '''
# Show Matplotlib colormaps
from pylab import *
from numpy import outer
rc('text', usetex=False)
a = outer(arange(0, 1, 0.01), ones(10))
plt.figure(figsize=(10, 5))
subplots_adjust(top=0.8, bottom=0.05, left=0.01, right=0.99)
maps=[m for m in cm.datad if not m.endswith("_r")]
maps.sort()
l = len(maps) + 1
for i, m in enumerate(maps):
plt.subplot(1, l, i + 1)
plt.axis("off")
plt.imshow(a, aspect='auto', cmap=get_cmap(m), origin="lower")
plt.title(m, rotation=90, fontsize=10)
# plt.savefig("colormaps.png", dpi=100, facecolor='gray') # 保存為png格式
plt.show()
Keras ImageDataGenerator and Data Augmentation¶
使用keras中的方法對圖像進行增強,例如:旋轉、裁剪、灰階化、平移、仿射變換...等¶
參攷: https://keras.io/preprocessing/image/¶
In [23]:
print(train_images.shape) # shape函數表示張量的形狀: (張數, 圖高, 圖寬, 通道數)
# reshape the images to 4D tensors
# train_data = np.asarray(train_images, dtype=float)
train_data = np.expand_dims(train_images, axis=-1) # 增加一維,即(張數, 圖高, 圖寬, 通道數), 灰階=1, 參攷
print(train_data.shape) # tensor: (張數, 圖高, 圖寬, 通道數)
# 秀出 100張測試圖片
tf2tools.plot_Images(train_data[0:100],
labels=train_labels[0:100],
rows=10,
figsize=(15, 15))
In [24]:
# 參攷 https://www.novatec-gmbh.de/en/blog/keras-data-augmentation-for-cnn/
# 秀出一張圖片
img = train_data[0]
print(img.shape) # shape函數表示張量的形狀: (圖高, 圖寬, 通道數)
img1 = img.reshape((1,) + img.shape) # reshape函數重新定義了原張量的維度, 即(張數, 圖高, 圖寬, 通道數)
print(img1.shape)
tf2tools.plot_Images(img1, figsize=(3, 3))
Shift¶
random_shift allows you to randomly shift by a given fraction of the imagesize in each direction. Here we specify wrg=0.1 and hrg=0.2. That means that we shift up to 0.2 x imagesize (0.2 x 28 = 5.6) pixel up or down and up to 0.1 x imagesize (0.1 x 28 = 2.8) pixel left or right.In all transformer functions you can specify row_axis, col_axis and channel_axis according to the array of images you pass into the function.
Input | Process | Output |
---|---|---|
img | keras.preprocessing.image.random_shift( ) | img_shifted |
In [26]:
# 秀出5張 shift 圖片
img_shifted = [ keras.preprocessing.image.random_shift(
img, # 輸入張量,必須是3維: (圖高, 圖寬, 通道數)
wrg=0.1, # width shift range, 寬度偏移範圍,作為寬度的浮動部分
hrg=0.2, # height shift range, 高度移動範圍,作為高度的浮動部分
row_axis=0, # 輸入張量中的行的軸索引
col_axis=1, # 輸入張量中的列的軸索引
channel_axis=2, # 輸入張量中的通道的軸的索引
fill_mode='constant', # 輸入的邊界之外的點根據給定的模式{常數}中的一個填充
cval=0. # 如果mode='constant',則用於輸入邊界以外的點的值
) for _ in range(5) ]
tf2tools.plot_Images(img_shifted, figsize=(7, 7))
Rotation¶
With the random_rotation transformer we can rotate the image randomly by up to x degrees clockwise or counterclockwise. Here we specify a maximum rotation of 20 degrees.Input | Process | Output |
---|---|---|
img | keras.preprocessing.image.random_rotation( ) | img_rotated |
In [27]:
# 秀出5張 rotate 圖片
img_rotated = [ keras.preprocessing.image.random_rotation(
img, # 輸入張量,必須是3維
rg=20, # 旋轉範圍,單位角度
row_axis=0, # 輸入張量中的行的軸索引
col_axis=1, # 輸入張量中的列的軸索引
channel_axis=2, # 輸入張量中的通道的軸的索引
fill_mode='constant', # 輸入的邊界之外的點根據給定的模式{常數}中的一個填充
cval=0. # 如果mode='constant',則用於輸入邊界以外的點的值
) for _ in range(5) ]
tf2tools.plot_Images(img_rotated, figsize=(7, 7))
Shear¶
The random_shear functions shears an image with a random shearing angle that is calculated from the given `intensity'.Note that shearing is different from just rotation since it deforms the given image by multiplying it with the following transformation matrix
Input | Process | Output |
---|---|---|
img | keras.preprocessing.image.random_shear( ) | img_sheared |
In [28]:
# 秀出5張 shear 圖片
img_sheared = [ keras.preprocessing.image.random_shear(
img,
intensity=0.4, # 角度轉換強度
row_axis=0,
col_axis=1,
channel_axis=2,
fill_mode='constant',
cval=0.
) for _ in range(5) ]
tf2tools.plot_Images(img_sheared, figsize=(7, 7))
Zoom¶
random_zoom zooms in and out of an image. But it don’t use the same zooming factor for horizontal and vertical zoom but two independently random values. We can specify a minimum (here 0.7) and a maximum value (here 1.3) for the zoom. A value bigger than 1.0 zooms in, thus making the object in the image bigger. A value smaller than 1.0 zooms out.Input | Process | Output |
---|---|---|
img | keras.preprocessing.image.random_zoom( ) | img_zoomed |
In [29]:
# 秀出5張 zoom 圖片
img_zoomed = [ keras.preprocessing.image.random_zoom(
img,
zoom_range=(0.7, 1.3), # 浮動的元組;縮放範圍的寬度和高度
row_axis=0,
col_axis=1,
channel_axis=2,
fill_mode='constant',
cval=0.
) for _ in range(5) ]
tf2tools.plot_Images(img_zoomed, figsize=(7, 7))
ImageDataGenerator¶
Now we combine every transformation that we just did in one ImageDataGenerator. It is also possibly to allow a flip of the image either horizontally or vertically. For now we disallow that option.When we start the ImageDataGenerator it runs in an endless loop. But since we just want a few example we let it run in a for loop and break out of it when we have collected enough examples.
This allows us to create 100 images from just one image.
In [30]:
# 資料增強增加訓練樣本
datagen = keras.preprocessing.image.ImageDataGenerator( # 影像預處理模組
rotation_range=20, # 角度值,0~180,影像旋轉
width_shift_range=0.1, # 水平平移,相對總寬度的比例
height_shift_range=0.1, # 垂直平移,相對總高度的比例
shear_range=0.5, # 剪切強度(以弧度逆時針方向剪切角度)
zoom_range=(0.9, 1.1), # 隨機縮放範圍
horizontal_flip=False, # 隨機水平翻轉
vertical_flip=False, # 隨機垂直翻轉
fill_mode='constant', # 填充新建立畫素的方法
cval=0 # 用於邊界之外的點的值
)
batches = 0
max_batches = 100
img_gen = []
# 產生隨機變換後圖像批量,迴圈是無限產生,需要手動指定終止條件
for x_batch in datagen.flow(img.reshape((1,) + img.shape), batch_size=max_batches):
img_gen.append(x_batch[0])
batches += 1
if batches >= max_batches:
# generator loops indefinetly
break
tf2tools.plot_Images(img_gen, rows=10, figsize=(10, 10))
將廠商給的圖片檔轉換成Dataset(EagerTensor)
- 提取資料(Extract):將資料從容器(硬碟、雲端等)提取
- 轉換資料(Transform):將資料轉換為模型可讀取的資料,同時進行數據清理等預處理
- 裝載資料(Load):將處理好的資料裝載至加速器(GPU)
In [ ]:
# !pip3 install --user -U pathlib
# !pip3 install --user -U random2
In [31]:
import pathlib
import random
import os
import cv2
AUTOTUNE = tf.data.experimental.AUTOTUNE # 使用自動調節管道找到 prefetching 的最佳參數
batch_size = 100 # 批次
num_classes = 4 # 類別
# --- 提取資料
# 印出目前工作目錄
currentDirectory = os.getcwd()
# print(type(currentDirectory))
data_root_orig = currentDirectory + "/liBattery"
# 抓取檔案
data_root = pathlib.Path(data_root_orig)
all_image_paths = list(data_root.glob('*/*'))
all_image_paths = [str(path) for path in all_image_paths]
# 將檔案打亂
random.shuffle(all_image_paths)
# print(len(all_image_paths))
# 將資料集分成 訓練:80% 及 測試:20%
r80 = (int)(len(all_image_paths) * 0.8)
train_image_paths = all_image_paths[:r80] # 80%
test_image_paths = all_image_paths[r80:] # 20%
train_image_count = len(train_image_paths)
test_image_count = len(test_image_paths)
# print(train_image_count)
# print(test_image_count)
# 列出目錄名稱=>標籤
label_names = sorted(dirs.name for dirs in data_root.glob('*/') if dirs.is_dir())
# print(label_names)
# 為每個標籤編流水號index
label_to_index = dict((name, index) for index, name in enumerate(label_names))
print(label_to_index)
print()
# 創建一個list,包含每個文件的標籤索引
all_image_labels = [label_to_index[pathlib.Path(path).parent.name] for path in all_image_paths]
train_image_labels = all_image_labels[:r80] # 80%
test_image_labels = all_image_labels[r80:] # 20%
print('All examples(100%): ', len(all_image_labels))
print('Train examples(80%):', len(train_image_labels))
print('Test examples(20%): ', len(test_image_labels))
# 秀出一張圖
tf2tools.show_img(train_image_paths[0], train_image_labels[0], label_names)
img = cv2.imread(train_image_paths[0])
print('Original image:', img.shape)
print()
# --- 轉換資料
# 使用 from_tensor_slices 方法將圖像數組切片,得到一個圖像數據集
train_path_ds = tf.data.Dataset.from_tensor_slices(train_image_paths)
test_path_ds = tf.data.Dataset.from_tensor_slices(test_image_paths)
# 創建一個新的數據集,通過在路徑數據集上映射 preprocess_image 來動態加載和格式化圖片
train_image_ds = train_path_ds.map(tf2tools.load_and_preprocess_image, num_parallel_calls=AUTOTUNE)
test_image_ds = test_path_ds.map(tf2tools.load_and_preprocess_image, num_parallel_calls=AUTOTUNE)
# 使用 from_tensor_slices 方法創建一個標籤數據集
train_label_ds = tf.data.Dataset.from_tensor_slices(tf.cast(train_image_labels, tf.int64))
test_label_ds = tf.data.Dataset.from_tensor_slices(tf.cast(test_image_labels, tf.int64))
# 由於這些數據集順序相同,可將它們打包在一起得到 (圖片,標籤) 數據集
train_image_label_ds = tf.data.Dataset.zip((train_image_ds, train_label_ds))
test_image_label_ds = tf.data.Dataset.zip((test_image_ds, test_label_ds))
# 將這對數組切片
train_ds = tf.data.Dataset.from_tensor_slices((train_image_paths, train_image_labels))
test_ds = tf.data.Dataset.from_tensor_slices((test_image_paths, test_image_labels))
train_image_label_ds = train_ds.map(tf2tools.load_and_preprocess_from_path_label)
test_image_label_ds = test_ds.map(tf2tools.load_and_preprocess_from_path_label)
# 設置一個和數據集大小一致的 shuffle buffer size(隨機緩衝區大小)以保證數據
train_ds = train_image_label_ds.shuffle(buffer_size=train_image_count)
train_ds = train_ds.batch(batch_size)
test_ds = test_image_label_ds.batch(batch_size)
train_ds = train_ds.prefetch(buffer_size=AUTOTUNE)
test_ds = test_ds.prefetch(buffer_size=AUTOTUNE)
train_image_batch, train_label_batch = next(iter(train_ds))
test_image_batch, test_label_batch = next(iter(test_ds))
train_label_batch = keras.utils.to_categorical(train_label_batch, num_classes)
test_label_batch = keras.utils.to_categorical(test_label_batch, num_classes)
print('Train dataset:', train_image_batch.shape)
print('Train type:', type(train_image_batch))
print('Test dataset: ', test_image_batch.shape)
MLP 架構圖 (對照組)¶
CNN架構圖¶
Set up the layers¶
The basic building block of a neural network is the layer. Layers extract representations from the data fed into them. Hopefully, these representations are meaningful for the problem at hand.Most of deep learning consists of chaining together simple layers. Most layers, such as
tf.keras.layers.Dense
, have parameters that are learned during training.
Keras 模型構建包括5個步驟:
- 定義(define)
- 編譯(compile)
- 訓練(fit)
- 評估(evaluate)
- 預測(prediction)
Don't do this cell⇩
In [ ]:
''' 此為[對照組]***不要執行***不要執行***不要執行*** '''
# MLP序列
train_shape = train_images.shape[1:] # 擷取訓練圖像的形狀
print(train_images.shape) # 即(張數, 圖高, 圖寬)
print(train_shape) # 即(圖高, 圖寬)
num_classes = len(class_names) # 擷取類別總數
# 定義一個簡單的序列(sequential)模型,多個網路層的線性堆疊,添加相應層次結構
def create_model():
model = keras.Sequential([ # 參攷[1]
keras.layers.Flatten(input_shape=train_shape,
name='flatten'), # 將輸入展平,不影響批量大小,input_shape:輸入數據的形狀, 參攷[2]
# 在第一層之後,就不再需要指定輸入的尺寸
keras.layers.Dense(units=512,
activation=tf.nn.relu,
kernel_initializer='normal',
bias_initializer='zeros',
name='fc1'), # 全連接層,units:神經元數量, activation:指定激活函數, 參攷[3]
keras.layers.Dropout(rate=0.2, name='dropout1'), # 防止過擬合 overfitting, 參攷 [4]
keras.layers.Dense(units=256, activation=tf.nn.relu, name='fc2'),
keras.layers.Dropout(rate=0.2, name='dropout2'),
keras.layers.Dense(units=num_classes,
activation=tf.nn.softmax,
name='output') # 參攷 [6]
])
# Compile the model
model.compile(optimizer='adam', # Optimizer, 基於數據及損失函數來更新模型, 參攷[7, 8]
loss='sparse_categorical_crossentropy', # Loss function, 希望轉向正確的方向並最小化此函數, 參攷[9]
metrics=['accuracy']) # 用於監視訓練和測試步驟, 參攷[10]
return model
Do this cell⇩
Input | Process | Output |
---|---|---|
train_shape | keras.Sequential( )...keras.layers.Conv2D( )...keras.layers.MaxPool2D( )...keras.layers.Dropout( )...keras.layers.Flatten( )...keras.layers.Dense( )... | model |
In [32]:
# CNN序列
train_shape = (train_images.shape[1:] + (1,)) # 擷取訓練圖像的形狀
print(train_images.shape) # 即(張數, 圖高, 圖寬)
print(train_shape) # 即(圖高, 圖寬)
num_classes = len(class_names) # 擷取類別總數
# del model # 刪除模型
# 定義一個簡單的序列(sequential)模型,多個網路層的線性堆疊,添加相應層次結構
def cnn_model():
model = keras.Sequential([ # 參攷[1]
keras.layers.Conv2D(filters=128,
kernel_size=3,
strides=1,
padding='same',
activation=tf.nn.relu,
input_shape=train_shape,
name='conv1'), # input_shape:輸入數據的形狀, 參攷[2]
# keras.layers.BatchNormalization(name='bn1'), # 參攷[11]
keras.layers.MaxPool2D(pool_size=2,
strides=2,
padding='same',
name='maxpool1'), # 參攷[12]
# keras.layers.Dropout(rate=0.1, name='dropoutc1'), # 防止過擬合 overfitting, 參攷 [4]
keras.layers.Conv2D(filters=256,
kernel_size=3,
strides=1,
padding='same',
activation=tf.nn.relu,
name='conv2'),
# keras.layers.BatchNormalization(name='bn2'),
keras.layers.MaxPool2D(pool_size=2,
strides=2,
padding='same',
name='maxpool2'),
# keras.layers.Dropout(rate=0.1, name='dropoutc2'),
keras.layers.Conv2D(filters=512,
kernel_size=3,
strides=1,
padding='same',
activation=tf.nn.relu,
name='conv3'),
# keras.layers.BatchNormalization(name='bn3'),
keras.layers.MaxPool2D(pool_size=2,
strides=2,
padding='same',
name='maxpool3'),
keras.layers.Dropout(rate=0.1, name='dropoutc3'),
keras.layers.Flatten(name='flatten'), # 將輸入展平,不影響批量大小
keras.layers.Dense(units=512,
activation=tf.nn.relu,
kernel_initializer='orthogonal', # 正交初始化權重
bias_initializer=tf.keras.initializers.constant(0.1), # 初始化偏置向量
name='fc1'), # 全連接層,units:神經元數量, activation:指定激活函數, 參攷[3]
# keras.layers.Dropout(rate=0.1, name='dropoutf1'), # 防止過擬合 overfitting
keras.layers.Dense(units=256,
activation=tf.nn.relu,
kernel_initializer='orthogonal',
bias_initializer=tf.keras.initializers.constant(0.1),
name='fc2'),
# keras.layers.Dropout(rate=0.1, name='dropoutf2'),
keras.layers.Dense(units=128,
activation=tf.nn.relu,
kernel_initializer='orthogonal',
bias_initializer=tf.keras.initializers.constant(0.1),
name='fc3'),
keras.layers.Dropout(rate=0.1, name='dropoutf3'),
keras.layers.Dense(units=num_classes,
activation=tf.nn.softmax,
name='output')
])
model.trainable = True
# Compile the model
model.compile(optimizer='adam', # Optimizer, 基於數據及損失函數來更新模型, 參攷[7, 8]
loss='sparse_categorical_crossentropy', # Loss function, 希望轉向正確的方向並最小化此函數, 參攷[9]
metrics=['accuracy']) # 用於監視訓練和測試步驟, 參攷[10]
return model
參攷:¶
- https://www.tensorflow.org/api_docs/python/tf/keras/Sequential
- https://www.tensorflow.org/api_docs/python/tf/keras/layers/Flatten
- https://www.tensorflow.org/api_docs/python/tf/keras/layers/Dense
- https://www.tensorflow.org/api_docs/python/tf/keras/layers/Dropout
- https://www.tensorflow.org/api_docs/python/tf/keras/layers/ReLU
- https://www.tensorflow.org/api_docs/python/tf/keras/layers/Softmax
- https://www.tensorflow.org/api_docs/python/tf/keras/Model#compile
- https://www.tensorflow.org/api_docs/python/tf/keras/optimizers/Adam
- https://www.tensorflow.org/api_docs/python/tf/keras/losses/sparse_categorical_crossentropy
- https://www.tensorflow.org/api_docs/python/tf/keras/metrics/Accuracy
- https://www.tensorflow.org/api_docs/python/tf/keras/layers/BatchNormalization
- https://www.tensorflow.org/api_docs/python/tf/keras/layers/MaxPool2D
In [33]:
# 創建一個基本的模型實例
model = cnn_model()
The first layer in this network,
After the pixels are flattened, the network consists of a sequence of two
tf.keras.layers.Flatten
, transforms the format of the images from a two-dimensional array (of 28 by 28 pixels) to a one-dimensional array (of 28 * 28 = 784 pixels). Think of this layer as unstacking rows of pixels in the image and lining them up. This layer has no parameters to learn; it only reformats the data.After the pixels are flattened, the network consists of a sequence of two
tf.keras.layers.Dense
layers. These are densely connected, or fully connected, neural layers. The first Dense
layer has 128 nodes (or neurons). The second (and last) layer is a 10-node softmax layer that returns an array of 10 probability scores that sum to 1. Each node contains a score that indicates the probability that the current image belongs to one of the 10 classes.Compile the model¶
Before the model is ready for training, it needs a few more settings. These are added during the model's compile step:- Loss function —This measures how accurate the model is during training. You want to minimize this function to "steer" the model in the right direction.
- Optimizer —This is how the model is updated based on the data it sees and its loss function.
- Metrics —Used to monitor the training and testing steps. The following example uses accuracy, the fraction of the images that are correctly classified.
In [34]:
# 顯示模型的結構
model.summary() # 參攷[1]
len(model.layers) # 參攷[2]
Out[34]:
Train the model¶
Training the neural network model requires the following steps:- Feed the training data to the model. In this example, the training data is in the
train_images
andtrain_labels
arrays. - The model learns to associate images and labels.
- You ask the model to make predictions about a test set—in this example, the
test_images
array. Verify that the predictions match the labels from thetest_labels
array.
model.fit
method—so called because it "fits" the model to the training data:
In [35]:
# 資料處理reshape the images to 4D tensors
train_cnn_images = np.expand_dims(train_images, axis=-1) # 增加一維,灰階=1, (張數, 圖高, 圖寬, 通道數)
test_cnn_images = np.expand_dims(test_images, axis=-1) # 同上
print(train_cnn_images.shape)
print(test_cnn_images.shape)
print()
import os
checkpoint_dir = "training_1"
# 若目錄不存在,則新建
if not os.path.exists(checkpoint_dir):
os.makedirs(checkpoint_dir)
checkpoint_path = "training_1/cp.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)
# 創建一個保存模型權重的callback
cp_callback = keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
save_weights_only=True, # save_best_only=True
verbose=1)
# 使用新的回調訓練模型, epochs=10, 輸出至 history, 建議使用 GPU
history = model.fit(x=train_cnn_images,
y=train_labels,
epochs=10,
validation_data=(test_cnn_images, test_labels),
callbacks=[cp_callback],
use_multiprocessing=True) # 通過回調訓練, 參攷
# 可能會生成與保存優化程序狀態相關的警告, 是防止過時使用=>可以忽略
In [36]:
# 秀出 checkpoint 檔案
# checkpoint_dir = "training_1"
!ls {checkpoint_dir}
# import os
# 刪除目錄
# os.system("rm -rf training_1")
創建一個新的未經訓練的模型。
僅恢復模型的權重時,必須具有與原始模型具有相同網路結構的模型。
由於模型具有相同的結構,可以
現在重建一個新的未經訓練的模型,並在測試集上進行評估。
未經訓練的模型將在機會水平(chance levels)上執行(準確度約為10%)
僅恢復模型的權重時,必須具有與原始模型具有相同網路結構的模型。
由於模型具有相同的結構,可以
共享權重
,儘管它是模型的不同實例。現在重建一個新的未經訓練的模型,並在測試集上進行評估。
未經訓練的模型將在機會水平(chance levels)上執行(準確度約為10%)
Input | Process | Output |
---|---|---|
x=test_cnn_images, y=test_labels | model.evaluate( ) | loss, acc |
In [37]:
# 創建一個基本模型實例
model = cnn_model()
# 評估模型
loss, acc = model.evaluate(x=test_cnn_images,
y=test_labels,
verbose=2,
use_multiprocessing=True) # 參攷
print("Untrained model, accuracy: {:5.2f}%".format(100 * acc))
然後從 checkpoint 加載權重並重新評估(準確度約為92%)¶
In [38]:
# 加載權重
model.load_weights(checkpoint_path) # 參攷
# 重新評估模型
loss, acc = model.evaluate(x=test_cnn_images,
y=test_labels,
verbose=2,
use_multiprocessing=True)
print("Restored model, accuracy: {:5.2f}%".format(100 * acc))
如果要進行測試,請重置模型並加載最新的 checkpoint(準確度約為92%)¶
In [39]:
# 刪除模型
del model
# 創建一個新的模型實例
model = cnn_model()
# 加載之前保存的權重
model.load_weights(checkpoint_path)
# 重新評估模型
loss, acc = model.evaluate(x=test_cnn_images,
y=test_labels,
verbose=2,
use_multiprocessing=True)
print("Restored model, accuracy: {:5.2f}%".format(100 * acc))
手動保存權重¶
如何將權重加載到模型中。使用Model.save_weights
方法手動保存它們。默認情況下,
tf.keras
和 save_weights
特別使用 TensorFlow checkpoints 格式 .ckpt 附檔名和 (保存在 "HDF5" 附檔名為 .h5 保存並序列化模型)
In [40]:
# 保存權重
model.save_weights('./checkpoints/my_checkpoint') # 參攷
# 創建模型實例
model = cnn_model()
# Restore the weights
model.load_weights('./checkpoints/my_checkpoint') # 參攷
# Evaluate the model
loss, acc = model.evaluate(x=test_cnn_images,
y=test_labels,
verbose=2,
use_multiprocessing=True)
print("Restored model, accuracy: {:5.2f}%".format(100 * acc))
In [41]:
# 秀出 checkpoints 檔案
!ls {"checkpoints"}
保存整個模型¶
模型和優化器可以保存到包含其狀態(權重和變量)和模型參數的文件中。這可以導出模型,以便在不訪問原始 python 代碼的情況下使用它。
而且可以通過恢復優化器狀態的方式,從中斷的位置恢復訓練。
保存完整模型會非常有用—可以在 TensorFlow.js (HDF5, Saved Model) 加載它們,然後在 web 瀏覽器中訓練和運行它們,
或者使用 TensorFlow Lite 將它們轉換為在移動設備上運行(HDF5, Saved Model)
將模型保存為HDF5文件¶
Keras 可以使用 HDF5 標準提供基本保存格式。可以將保存的模型視為單個二進位blob參攷: https://tensorflow.google.cn/federated/api_docs/python/tff/simulation/HDF5ClientData?hl=en¶
In [42]:
# !pip3 install h5py
# 創建一個新的模型實例
model = cnn_model()
# 訓練模型, epochs=5
model.fit(x=train_cnn_images,
y=train_labels,
epochs=5,
use_multiprocessing=True)
# 將整個模型保存為HDF5文件
model.save('my_model.h5')
In [43]:
# del new_model # 刪除現有模型
# 重新創建完全相同的模型,包括其權重和優化程序
new_model = keras.models.load_model('my_model.h5') # 參攷
# 顯示網路結構
new_model.summary()
In [44]:
# 檢查準確率(accuracy)
loss, acc = new_model.evaluate(x=test_cnn_images,
y=test_labels,
verbose=2,
use_multiprocessing=True)
print("Restored model, accuracy: {:5.2f}%".format(100 * acc))
從 HDF5文件 顯示各層次名稱及權重等¶
In [45]:
# del loaded_model # 刪除現有模型
# 加載模型並對模型進行調整
loaded_model = keras.models.load_model('my_model.h5')
# 修改 model's name
loaded_model._name = 'cnn_model'
loaded_model.summary()
print('Original layers:', len(loaded_model.layers))
print()
# 列印各層名字,權重的形狀
for layer in loaded_model.layers: # 參攷
for weight in layer.weights:
print(layer.name, weight.name, weight.shape)
print()
# 列印單層
layer_name = 'conv1'
print(loaded_model.get_layer(layer_name).name)
# print(loaded_model.get_layer('conv1').get_weights())
print()
# 列印最後一層
print(loaded_model.layers[-1].input)
print(loaded_model.layers[-1].output)
print()
loaded_model._layers.pop(1) # 刪除第一層
loaded_model._layers.pop(-1) # 刪除最後一層
loaded_model.summary()
print('After layers:', len(loaded_model.layers))
In [46]:
# Exports the Trackable object obj to SavedModel format
tf.saved_model.save(model, 'saved_model/') # 參攷[1-3]
In [47]:
# 秀出 saved_model 檔案
!ls {'saved_model'}
tf2tools.get_size('saved_model')
# 刪除目錄
# os.system("rm -rf saved_model")
Evaluate accuracy¶
Next, compare how the model performs on the test dataset:
In [48]:
# 評估
test_loss, test_acc = model.evaluate(x=test_cnn_images,
y=test_labels,
verbose=2,
use_multiprocessing=True) # 參攷
print('\nTest accuracy:', test_acc, '\tLoss:', test_loss)
Make predictions¶
With the model trained, you can use it to make predictions about some images.
It turns out that the accuracy on the test dataset is a little less than the accuracy on the training dataset. This gap between training accuracy and test accuracy represents overfitting. Overfitting is when a machine learning model performs worse on new, previously unseen inputs than on the training data.
Input | Process | Output |
---|---|---|
x=test_cnn_images | model.predict( ) | predictions |
In [49]:
# 預測
predictions = model.predict(x=test_cnn_images, use_multiprocessing=True) # 參攷
Here, the model has predicted the label for each image in the testing set. Let's take a look at the first prediction:
Input | Process | Output |
---|---|---|
0 | predictions[ ] | [1.9726464e-19, 5.6842889e-20, 1.3350342e-19, ..., 9.9999952e-01] |
In [50]:
# 秀出 第一個預測結果
predictions[0]
Out[50]:
A prediction is an array of 10 numbers. They represent the model's "confidence" that the image corresponds to each of the 10 different articles of clothing. You can see which label has the highest confidence value:
Input | Process | Output |
---|---|---|
predictions[0] | np.argmax(predictions[ ]) | 9 |
In [51]:
# 返回最大值索引
np.argmax(predictions[0]) # 參攷
Out[51]:
So, the model is most confident that this image is an ankle boot, or
class_names[9]
. Examining the test label shows that this classification is correct:
In [52]:
# 秀出 相對位置的 標籤(類別編號)
test_labels[0]
Out[52]:
In [53]:
# 判斷 預測結果 是否相等於 標籤(答案)
np.argmax(predictions[0]) == test_labels[0]
Out[53]:
In [54]:
# 秀出 類別名稱
class_names[np.argmax(predictions[0])]
Out[54]:
In [55]:
# 預測結果視覺化
# Plot the first X test images, their predicted labels, and the true labels.
# Color correct predictions in blue and incorrect predictions in red.
tf2tools.plot_predict(predictions, test_labels, test_images)
顯示訓練歷史記錄的trend圖表¶
In [56]:
# list all data in history
print(history.history.keys()) # 參攷
# 顯示準確率圖表summarize history for accuracy
key = 'accuracy'
tf2tools.history_plot(history, key)
# 顯示損失函數誤差值圖表summarize history for loss
key = 'loss'
tf2tools.history_plot(history, key)
顯示混淆矩陣(confusion matrix)¶
In [57]:
import seaborn as sns # 參攷[1]
from sklearn.metrics import confusion_matrix # 參攷[2]
# predict
y_pred = model.predict_classes(x=test_cnn_images) # 參攷[3]
# print(y_pred)
# 混淆矩陣:真實值與預測值的對比
# 對角線上的值表示預測正確的數量/比例;非對角線元素是預測錯誤的部分
con_mat = confusion_matrix(test_labels, y_pred)
con_mat_norm = con_mat.astype('float') / con_mat.sum(axis=1)[:, np.newaxis] # 歸一化
con_mat_norm = np.around(con_mat_norm, decimals=2)
# plot
figure = plt.figure(figsize=(8, 8))
sns.heatmap(con_mat_norm, annot=True, cmap='Blues')
plt.ylim(0, 10)
plt.xlabel('Predicted labels')
plt.ylabel('True labels')
plt.show()
class_names[6]
Out[57]:
找出預測錯誤的資料¶
In [58]:
# 用訓練好的 Model 進行 辨識物體圖片
prediction = model.predict_classes(x=test_cnn_images)
# 顯示 測試圖片集 全部的預測結果
print(prediction)
# 顯示 圖片集 第 340~360 筆的預測結果
print(prediction[340:360])
# 透過 DataFrame 對照表清單, 來顯示 Label 真實數值, 與 AI 預設結果
import pandas as pd # 參攷[1]
# Pandas.DataFrame 的資料集需要一維陣列, 而 test_labels 本身是二維陣列, 需透過 reshape 轉換為一維陣列
test_labels_onearr = test_labels.reshape(len(test_labels))
# print(test_labels_onearr.shape)
print()
checkList = pd.DataFrame(data={ # 參攷[2]
'label': test_labels_onearr, # Column1 名稱: 欄位值集合 (Label 真實數值)
'prediction': prediction # Column2 名稱: 欄位值集合 (CNN 預測結果)
})
# 顯示對照表前 10 筆結果
print(checkList[:10])
print()
# 列出對照表中, prediction 欄位值 不等於 label 欄位值的資料
checkList[checkList.prediction != checkList.label]
Out[58]:
In [59]:
# demonstration of calculating metrics for a neural network model using sklearn(Scikit-learn)
# Model evaluation: quantifying the quality of predictions, 參攷[1]
# from sklearn.datasets import make_circles
from sklearn.metrics import accuracy_score # 參攷[2]
from sklearn.metrics import precision_score # 參攷[3]
from sklearn.metrics import recall_score # 參攷[4]
from sklearn.metrics import f1_score # 參攷[5]
from sklearn.metrics import cohen_kappa_score # 參攷[6]
from sklearn.metrics import roc_auc_score # 參攷[7]
from sklearn.metrics import confusion_matrix # 參攷[8]
# predict probabilities for test set
y_probs = model.predict(x=test_cnn_images, verbose=0, use_multiprocessing=True) # 參攷[8]
# predict crisp classes for test set
y_classes = model.predict_classes(x=test_cnn_images, verbose=0) # 參攷[9]
# reduce to 1d array
# y_probs = y_probs[:, 0]
# y_classes = y_classes[:, 0]
# accuracy: (tp + tn) / (p + n)
accuracy = accuracy_score(test_labels, y_classes)
print('Accuracy: %f' % accuracy)
# precision tp / (tp + fp)
precision = precision_score(test_labels, y_classes, average='weighted')
print('Precision: %f' % precision)
# recall: tp / (tp + fn)
recall = recall_score(test_labels, y_classes, average='weighted')
print('Recall: %f' % recall)
print()
# f1: 2 tp / (2 tp + fp + fn)
f1 = f1_score(test_labels, y_classes, average='weighted')
print('F1 score: %f' % f1)
print()
# kappa
kappa = cohen_kappa_score(test_labels, y_classes)
print('Cohens kappa: %f' % kappa)
# ROC AUC
# auc = roc_auc_score(test_labels, y_probs)
# print('ROC AUC: %f' % auc)
# confusion matrix
print()
matrix = confusion_matrix(test_labels, y_classes)
print(matrix)
參攷:¶
- https://scikit-learn.org/stable/modules/model_evaluation.html#model-evaluation
- https://scikit-learn.org/stable/modules/generated/sklearn.metrics.accuracy_score.html
- https://scikit-learn.org/stable/modules/generated/sklearn.metrics.precision_score.html
- https://scikit-learn.org/stable/modules/generated/sklearn.metrics.recall_score.html
- https://scikit-learn.org/stable/modules/generated/sklearn.metrics.f1_score.html
- https://scikit-learn.org/stable/modules/generated/sklearn.metrics.cohen_kappa_score.html
- https://scikit-learn.org/stable/modules/generated/sklearn.metrics.roc_auc_score.html
- https://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html
- https://www.tensorflow.org/api_docs/python/tf/keras/Model#predict
- https://www.tensorflow.org/api_docs/python/tf/keras/Sequential#predict_classes
The end.
In [ ]:
留言