AI影像辨識
宣傳影片 

0. 準備資料
0.1 影像資料
首先,準備好要用到的訓練與測試資料集。
我們使用貓與狗的圖片資料來訓練貓狗辨識模型。
範例資料採用貓與狗各4000張圖片來訓練,並以各1000張照片做測試。
範例資料格式如下:

我們可以先預覽圖片:
library(dplyr)
library(keras)
## Sample Images
par(mfrow = c(6, 12), pty = "s", mar = c(0.2, 0.2, 0, 0))
for(x in c("cat","dog")) for(i in 1:36)
sprintf("dataset/training_set/%ss/%s.%d.jpg", x, x, i) %>%
image_load(target_size=c(150,150)) %>%
image_to_array %>% as.raster(255) %>% plot

可以發現很多難以辨識的圖片,但是透過訓練,電腦將可以快速且高準確率的辨識這些圖片唷。
0.2 資料讀取
因為資料集很大,我們沒有辦法一次讀取所有資料來訓練,我們設定函數一次提取特定數量的資料,並對其做處理。
img255 = image_data_generator(rescale = 1/255)
Generate = function(x, gen=img255, sz=20) flow_images_from_directory(
x, gen,
target_size = c(150, 150),
batch_size = sz,
class_mode = "binary"
)
1. CNN模型(Convolutional Neural Network)
CNN模型是很常見的圖像識別模型,其概念可以參考2分鐘短片:CNN簡介
1.1 使用Keras建立CNN模型
cnn1 <- keras_model_sequential() %>%
layer_conv_2d(filters = 32, kernel_size = c(3, 3), activation = "relu",
input_shape = c(150, 150, 3)) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_flatten() %>%
layer_dense(units = 512, activation = "relu") %>%
layer_dense(units = 1, activation = "sigmoid")
summary(cnn1)

1.2 設定模型訓練參數
cnn1 %>% compile(
loss = "binary_crossentropy",
optimizer = optimizer_rmsprop(lr = 1e-4),
metrics = c("acc")
)
1.3 開始訓練
fit1 <- cnn1 %>% fit_generator(
Generate("dataset/training_set"),
steps_per_epoch = 200,
epochs = 20,
validation_data = Generate("dataset/test_set"),
validation_steps = 50,
verbose=2
)

將模型訓練過程繪製成圖表
plot(fit1)

acc表示準確率。
經過20次迭代的訓練,模型已經可以有接近9成的準確率囉。
2. 資料擴充
常常我們所擁有的圖像資料集是不足的,這時可以將所擁有的資料做一些變化後當作新的資料,例如,將圖片反轉、切割、變形。這些內容都可以當作新的資料,幫助模型學會看懂不同方向、大小或有雜訊的圖片。
2.1 製作一個擴充資料的資料產生函數
Augment = image_data_generator(
rescale = 1/255,
rotation_range = 40,
width_shift_range = 0.2,
height_shift_range = 0.2,
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip = TRUE,
fill_mode = "nearest"
)
img = image_load("dataset/training_set/cats/cat.28.jpg", target_size=c(150,150)) %>%
image_to_array %>% array_reshape(c(1,150,150,3))
aug = flow_images_from_data(img, generator=Augment, batch_size=1)
par(mfrow = c(2, 6), pty = "s", mar = c(0.5, 0.5, 0, 0))
for (i in 1:12) generator_next(aug)[1,,,] %>% as.raster %>% plot

可由測試看出,我們將一張圖片做了許多旋轉與移動,成為了新的圖片。
2.2 訓練模型
這裡我們使用與上面相同的CNN模型
cnn2 <- keras_model_sequential() %>%
layer_conv_2d(filters = 32, kernel_size = c(3, 3), activation = "relu",
input_shape = c(150, 150, 3)) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_flatten() %>%
layer_dropout(rate = 0.5) %>%
layer_dense(units = 512, activation = "relu") %>%
layer_dense(units = 1, activation = "sigmoid")
cnn2 %>% compile(
loss = "binary_crossentropy",
optimizer = optimizer_rmsprop(lr = 1e-4),
metrics = c("acc")
)
summary(cnn2)
使用資料擴充的方式來訓練。
fit2 <- cnn2 %>% fit_generator(
Generate("dataset/training_set", Augment, 40),
steps_per_epoch = 200,
epochs = 20,
validation_data = Generate("dataset/test_set"),
validation_steps = 50,
verbose=2
)
最後一樣以圖表觀察訓練過程。
plot(fit2)

在這裡validation的資料及準確度反而較高,是因為對於validation資料我們並沒有做資料擴充,故模型並沒有預測經過變化的樣本。
3. 使用預訓練模型
訓練一個辨識模型需要很多的資料,且需要很多訓練時間才能達到好的效果。因此,我們可以直接使用網路上人家訓練好的模型(也叫做預訓練模型),減少自己訓練的成本。這裡我們實作調整 VGG16 預訓練模型,來達到快速訓練模型的效果。
3.1 固定預訓練模型
引入預訓練好的 VGG16 圖像辨識模型
conv_base <- application_vgg16(
weights = "imagenet",
include_top = FALSE, #將最後的輸出層移除
input_shape = c(150, 150, 3))
summary(conv_base)

可以看見 VGG16 辨識模型並沒有最後的輸出層,我們只要該模型前段對圖片特徵的萃取能力。
接著將我們要訓練的輸出層接上去。
cnn3 <- keras_model_sequential()
conv_base
layer_flatten()
layer_dense(units = 256, activation = "relu")
layer_dense(units = 1, activation = "sigmoid")
summary(cnn3)

我們只要訓練輸出層即可,將 VGG16 的權重固定(待會訓練時不更新權重)。
length(cnn3$trainable_weights)
30
原先可訓練的層數是30層。
freeze_weights(conv_base)
length(cnn3$trainable_weights)
4
現在只訓練最後4層。
開始訓練。
cnn3 %>% compile(
loss = "binary_crossentropy",
optimizer = optimizer_rmsprop(lr = 2e-5),
metrics = c("accuracy"))
fit3 <- cnn3 %>% fit_generator(
Generate("dataset/training_set",Augment,40),
steps_per_epoch = 100,
epochs = 30,
validation_data = Generate("dataset/test_set"),
validation_steps = 50,
verbose = 2
)
plot(fit3)

比起先前重新訓練的模型,可發現此模型很快就有一定的準確率,且準確率也更高,這就是預訓練模型的效果。
3.2 微調預訓練模型
CNN模型中,越靠近輸出層的層萃取的內容越高層,例如,前面層都抓取線條或顏色等資訊,在後面層可能就產生了人、動物、物品等資訊。所以我們可以微調後面層的權重,來達到對特定目標的辨識。
剛剛我們固定了預訓練模型的權重,現在我們將後面幾層的權重一起訓練。
unfreeze_weights(conv_base, from = "block5_conv1")
length(cnn3$trainable_weights) # 10
10
原先是4層,現在又多訓練了6層。
開始訓練。
cnn3 %>% compile(
loss = "binary_crossentropy",
optimizer = optimizer_rmsprop(lr = 1e-5),
metrics = c("accuracy")
)
fit3a = cnn3 %>% fit_generator(
Generate("dataset/training_set",Augment,40),
steps_per_epoch = 200,
epochs = 30,
validation_data = Generate("dataset/test_set"),
validation_steps = 50,
verbose = 2
)
plot(fit3a)

可看見準確率又有顯著上升,已經到達95%的準確率了,現在你也可以試試創作自己的影像辨識模型囉!
AI影像辨識
宣傳影片

0. 準備資料
0.1 影像資料
首先,準備好要用到的訓練與測試資料集。

我們使用貓與狗的圖片資料來訓練貓狗辨識模型。
範例資料採用貓與狗各4000張圖片來訓練,並以各1000張照片做測試。
範例資料格式如下:
我們可以先預覽圖片:
library(dplyr) library(keras) ## Sample Images par(mfrow = c(6, 12), pty = "s", mar = c(0.2, 0.2, 0, 0)) for(x in c("cat","dog")) for(i in 1:36) sprintf("dataset/training_set/%ss/%s.%d.jpg", x, x, i) %>% image_load(target_size=c(150,150)) %>% image_to_array %>% as.raster(255) %>% plot
可以發現很多難以辨識的圖片,但是透過訓練,電腦將可以快速且高準確率的辨識這些圖片唷。
0.2 資料讀取
因為資料集很大,我們沒有辦法一次讀取所有資料來訓練,我們設定函數一次提取特定數量的資料,並對其做處理。
img255 = image_data_generator(rescale = 1/255) #將圖片像素值標準化至0~1之間 Generate = function(x, gen=img255, sz=20) flow_images_from_directory( x, gen, target_size = c(150, 150), # 壓縮圖片成一致大小 batch_size = sz, # 一次抽取的樣本數 class_mode = "binary" # 圖片類別為二元類別(貓或狗) )
1. CNN模型(Convolutional Neural Network)
CNN模型是很常見的圖像識別模型,其概念可以參考2分鐘短片:CNN簡介
1.1 使用Keras建立CNN模型
cnn1 <- keras_model_sequential() %>% layer_conv_2d(filters = 32, kernel_size = c(3, 3), activation = "relu", # filters: filter個數 input_shape = c(150, 150, 3)) %>% # kernel_size: filter的長寬 layer_max_pooling_2d(pool_size = c(2, 2)) %>% layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = "relu") %>% layer_max_pooling_2d(pool_size = c(2, 2)) %>% layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>% layer_max_pooling_2d(pool_size = c(2, 2)) %>% layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>% layer_max_pooling_2d(pool_size = c(2, 2)) %>% layer_flatten() %>% # 將特徵展開為一維向量 layer_dense(units = 512, activation = "relu") %>% layer_dense(units = 1, activation = "sigmoid") summary(cnn1)
1.2 設定模型訓練參數
cnn1 %>% compile( loss = "binary_crossentropy", #目標損失函數 optimizer = optimizer_rmsprop(lr = 1e-4), #訓練優化方法 metrics = c("acc") #評價方式 )
1.3 開始訓練
fit1 <- cnn1 %>% fit_generator( #自訂輸入資料 Generate("dataset/training_set"), #先前定義好的函數 steps_per_epoch = 200, #每次迭代輸入幾次資料 epochs = 20, #迭代次數 validation_data = Generate("dataset/test_set"), validation_steps = 50, verbose=2 #顯示訓練過程 )
將模型訓練過程繪製成圖表
plot(fit1)
acc表示準確率。
經過20次迭代的訓練,模型已經可以有接近9成的準確率囉。
2. 資料擴充
常常我們所擁有的圖像資料集是不足的,這時可以將所擁有的資料做一些變化後當作新的資料,例如,將圖片反轉、切割、變形。這些內容都可以當作新的資料,幫助模型學會看懂不同方向、大小或有雜訊的圖片。
2.1 製作一個擴充資料的資料產生函數
Augment = image_data_generator( rescale = 1/255, rotation_range = 40, width_shift_range = 0.2, height_shift_range = 0.2, shear_range = 0.2, zoom_range = 0.2, horizontal_flip = TRUE, fill_mode = "nearest" ) # Load and Reshape an image for testing img = image_load("dataset/training_set/cats/cat.28.jpg", target_size=c(150,150)) %>% image_to_array %>% array_reshape(c(1,150,150,3)) # Test the Aug. Generator aug = flow_images_from_data(img, generator=Augment, batch_size=1) par(mfrow = c(2, 6), pty = "s", mar = c(0.5, 0.5, 0, 0)) for (i in 1:12) generator_next(aug)[1,,,] %>% as.raster %>% plot
可由測試看出,我們將一張圖片做了許多旋轉與移動,成為了新的圖片。
2.2 訓練模型
這裡我們使用與上面相同的CNN模型
cnn2 <- keras_model_sequential() %>% layer_conv_2d(filters = 32, kernel_size = c(3, 3), activation = "relu", input_shape = c(150, 150, 3)) %>% layer_max_pooling_2d(pool_size = c(2, 2)) %>% layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = "relu") %>% layer_max_pooling_2d(pool_size = c(2, 2)) %>% layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>% layer_max_pooling_2d(pool_size = c(2, 2)) %>% layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>% layer_max_pooling_2d(pool_size = c(2, 2)) %>% layer_flatten() %>% layer_dropout(rate = 0.5) %>% layer_dense(units = 512, activation = "relu") %>% layer_dense(units = 1, activation = "sigmoid") cnn2 %>% compile( loss = "binary_crossentropy", optimizer = optimizer_rmsprop(lr = 1e-4), metrics = c("acc") ) summary(cnn2)
使用資料擴充的方式來訓練。
fit2 <- cnn2 %>% fit_generator( Generate("dataset/training_set", Augment, 40), steps_per_epoch = 200, epochs = 20, validation_data = Generate("dataset/test_set"), validation_steps = 50, verbose=2 )
最後一樣以圖表觀察訓練過程。
plot(fit2)
在這裡validation的資料及準確度反而較高,是因為對於validation資料我們並沒有做資料擴充,故模型並沒有預測經過變化的樣本。
3. 使用預訓練模型
訓練一個辨識模型需要很多的資料,且需要很多訓練時間才能達到好的效果。因此,我們可以直接使用網路上人家訓練好的模型(也叫做預訓練模型),減少自己訓練的成本。這裡我們實作調整 VGG16 預訓練模型,來達到快速訓練模型的效果。
3.1 固定預訓練模型
引入預訓練好的 VGG16 圖像辨識模型
conv_base <- application_vgg16( weights = "imagenet", include_top = FALSE, #將最後的輸出層移除 input_shape = c(150, 150, 3)) summary(conv_base)
可以看見 VGG16 辨識模型並沒有最後的輸出層,我們只要該模型前段對圖片特徵的萃取能力。
接著將我們要訓練的輸出層接上去。
cnn3 <- keras_model_sequential() %>% conv_base %>% layer_flatten() %>% layer_dense(units = 256, activation = "relu") %>% layer_dense(units = 1, activation = "sigmoid") summary(cnn3)
我們只要訓練輸出層即可,將 VGG16 的權重固定(待會訓練時不更新權重)。
length(cnn3$trainable_weights)
30
原先可訓練的層數是30層。
freeze_weights(conv_base) # 將VGG16的權重改為不訓練 length(cnn3$trainable_weights) # 4
4
現在只訓練最後4層。
開始訓練。
cnn3 %>% compile( loss = "binary_crossentropy", optimizer = optimizer_rmsprop(lr = 2e-5), metrics = c("accuracy"))
fit3 <- cnn3 %>% fit_generator( Generate("dataset/training_set",Augment,40), steps_per_epoch = 100, epochs = 30, validation_data = Generate("dataset/test_set"), validation_steps = 50, verbose = 2 )
plot(fit3)
比起先前重新訓練的模型,可發現此模型很快就有一定的準確率,且準確率也更高,這就是預訓練模型的效果。
3.2 微調預訓練模型
CNN模型中,越靠近輸出層的層萃取的內容越高層,例如,前面層都抓取線條或顏色等資訊,在後面層可能就產生了人、動物、物品等資訊。所以我們可以微調後面層的權重,來達到對特定目標的辨識。
剛剛我們固定了預訓練模型的權重,現在我們將後面幾層的權重一起訓練。
unfreeze_weights(conv_base, from = "block5_conv1") length(cnn3$trainable_weights) # 10
10
原先是4層,現在又多訓練了6層。
開始訓練。
cnn3 %>% compile( loss = "binary_crossentropy", optimizer = optimizer_rmsprop(lr = 1e-5), metrics = c("accuracy") )
fit3a = cnn3 %>% fit_generator( Generate("dataset/training_set",Augment,40), steps_per_epoch = 200, epochs = 30, validation_data = Generate("dataset/test_set"), validation_steps = 50, verbose = 2 )
plot(fit3a)
可看見準確率又有顯著上升,已經到達95%的準確率了,現在你也可以試試創作自己的影像辨識模型囉!