Tăng cường dữ liệu hình ảnh cho Deep Learning

Hiểu tăng cường dữ liệu hình ảnh là gì và cách sử dụng nó bằng Keras cho các dự án deep learning của bạn

Photo by Chris Lawton on Unsplash

Nếu bạn đã từng thử thực hiện nhận dạng hình ảnh bằng học sâu, bạn sẽ biết tầm quan trọng của một tập dữ liệu tốt cho việc đào tạo. Tuy nhiên, việc tìm đủ hình ảnh để huấn luyện không phải lúc nào cũng dễ dàng và độ chính xác của mô hình của bạn phụ thuộc trực tiếp vào chất lượng của dữ liệu huấn luyện.

May mắn thay, có những kỹ thuật bạn có thể sử dụng để bổ sung cho tập dữ liệu hình ảnh mà họ sử dụng để đào tạo. Một trong những kỹ thuật được gọi là tăng cường dữ liệu hình ảnh. Trong bài viết này, tôi sẽ thảo luận về tăng cường dữ liệu hình ảnh là gì, cách thức hoạt động, tại sao nó hữu ích trong học sâu và cuối cùng là cách thực hiện tăng cường dữ liệu hình ảnh bằng thư viện Keras.

Tăng cường dữ liệu hình ảnh là một kỹ thuật mà tạo hình ảnh mới từ những hình ảnh hiện có. Để làm được điều đó, bạn thực hiện một số thay đổi nhỏ đối với chúng, chẳng hạn như điều chỉnh độ sáng của ảnh, xoay ảnh hoặc dịch chuyển chủ thể trong ảnh theo chiều ngang hoặc chiều dọc.

Kỹ thuật tăng cường hình ảnh cho phép bạn tăng kích thước của tập huấn luyện một cách giả tạo, từ đó cung cấp nhiều dữ liệu hơn cho mô hình huấn luyện của bạn. Điều này cho phép bạn cải thiện độ chính xác của mô hình bằng cách nâng cao khả năng mô hình của bạn nhận ra các biến thể mới của dữ liệu huấn luyện.

Các loại tăng cường dữ liệu hình ảnh

Tính năng nâng cao hình ảnh có nhiều dạng, sau đây là một số dạng phổ biến - Dịch chuyển dọc, Dịch chuyển ngang, Lật dọc, Lật ngang, Xoay, Điều chỉnh độ sáng và Phóng to/Thu nhỏ.

Trước tiên tôi sẽ trình bày các kỹ thuật tăng cường hình ảnh khác nhau bằng Python và Keras. Nếu bạn muốn dùng thử, hãy đảm bảo bạn đã cài đặt các phần mềm và gói sau:

Sau khi Anaconda và TensorFlow được cài đặt, hãy tạo Notebook Jupyter mới.

Dịch chuyển dọc

Kỹ thuật tăng cường hình ảnh đầu tiên mà tôi muốn trình bày là dịch chuyển dọc. Các dịch chuyển dọc ngẫu nhiên dịch chuyển hình ảnh theo chiều dọc lên hoặc xuống. Trong ví dụ này, tôi sẽ sử dụng một hình ảnh có tên 747.jpg, nằm trong cùng thư mục với Notebook Jupyter của tôi.

Nguồn hình ảnh: https://commons.wikimedia.org/wiki/File:Qantas_Boeing_747-438ER_VH-OEI_at_LAX.jpg. Tập tin này được cấp phép theo Creative Commons Attribution-Share Alike 2.0 Chung giấy phép.

Đoạn mã sau đây sử dụng ImageDataGenerator class trong Keras để dịch chuyển hình ảnh theo chiều dọc.

Sản phẩm ImageDataGenerator lớp từ Keras tạo ra các lô dữ liệu hình ảnh với tính năng tăng cường dữ liệu theo thời gian thực.

#---nhập mô-đun---
nhập numpy dưới dạng np
nhập matplotlib.pyplot dưới dạng plt
từ nhập tensorflow.keras.preprocessing.image tải_img
từ tensorflow.keras.preprocessing.image nhập img_to_array
từ tensorflow.keras.preprocessing.image nhập ImageDataGenerator
#---tải hình ảnh---
image_filename = '747.jpg'
img = tải_img(tên_tệp_hình ảnh)
#---chuyển đổi hình ảnh sang mảng 3D---
dữ liệu hình ảnh = img_to_array(img)
#---chuyển đổi thành mảng 4-D gồm 1 phần tử của mảng 3D biểu diễn
# bức hình---
hình ảnh_data = np.expand_dims(image_data, axis=0)
#---tạo trình tạo tăng cường dữ liệu hình ảnh---
datagen = ImageDataGenerator(width_shift_range=0.2)
#---chuẩn bị trình vòng lặp; flow() nhận vào một mảng 4D và trả về
# một iterator chứa một loạt ảnh---
train_generator = datagen.flow(images_data, batch_size=1)
hàng = 5
cột = 4
#--- vẽ 5 hàng và 4 cột---
fig, axes = plt.subplots(hàng,cột)
cho r trong phạm vi (hàng):
cho c trong phạm vi (cột):
#---lấy hình ảnh tiếp theo trong đợt (một hình ảnh kể từ đợt
# kích thước là 1)---
image_batch = train_generator.next()

#---chuyển đổi sang số nguyên không dấu để xem---
hình ảnh = image_batch[0].astype('uint8')

#---đưa hình ảnh---
trục[r,c].imshow(hình ảnh)
#---đặt kích thước của hình---
fig.set_size_inches(15,10)

Đoạn mã trên tạo ra kết quả đầu ra sau:

Như bạn có thể thấy từ kết quả ở trên, mỗi lần bạn gọi next() phương pháp từ train_generator đối tượng, bạn sẽ có được một hình ảnh bị thay đổi một chút. Trong đoạn mã trên, một hình ảnh mới được dịch chuyển 20% dựa trên chiều cao của hình ảnh ban đầu sẽ được trả về mỗi khi bạn gọi phương thức next() phương pháp:

datagen = ImageDataGenerator(width_shift_range=0.2)

Điều thú vị là đối với phiên bản này ImageDataGenerator (tensorflow.keras.preprocessing.image) lớp, chỉ định width_shift_range tham số sẽ dịch chuyển hình ảnh theo chiều dọc, thay vì theo chiều ngang (đó là hành vi của phiên bản cũ hơnImageDataGeneratortừ keras.preprocessing.image mô-đun). Tương tự như vậy, nếu bạn muốn hình ảnh được dịch chuyển theo chiều ngang, bạn cần sử dụng height_shift_range tham số (xem phần tiếp theo).

Lưu ý rằng next() phương thức sẽ trả về một hình ảnh được tăng cường bao nhiêu lần tùy thích. Trong đoạn mã trên, chúng tôi đã gọi nó 20 lần (5 hàng nhân 4 cột).

Dịch chuyển ngang

Bây giờ bạn có thể thử dịch chuyển hình ảnh theo chiều ngang bằng cách sử dụng height_shift_range tham số:

datagen = ImageDataGenerator(chiều cao_shift_range=0.2)
train_generator = datagen.flow(images_data, batch_size=1)
hàng = 5
cột = 4
fig, axes = plt.subplots(hàng,cột)
cho r trong phạm vi (hàng):
cho c trong phạm vi (cột):
image_batch = train_generator.next()
hình ảnh = image_batch[0].astype('uint8')
trục[r,c].imshow(hình ảnh)
fig.set_size_inches(15,10)

Đoạn mã trên tạo ra kết quả đầu ra sau:

Lật ngang

Đôi khi việc lật hình ảnh theo chiều ngang là điều hợp lý. Trong trường hợp máy bay, mặt trước của máy bay có thể hướng về bên trái hoặc bên phải:

datagen = ImageDataGenerator(Horizontal_flip=Đúng)
train_generator = datagen.flow(images_data, batch_size=1)
hàng = 2
cột = 2
fig, axes = plt.subplots(hàng,cột)
cho r trong phạm vi (hàng):
cho c trong phạm vi (cột):
image_batch = train_generator.next()
hình ảnh = image_batch[0].astype('uint8')
trục[r,c].imshow(hình ảnh)
fig.set_size_inches(15,10)

Đối với đoạn mã ở trên, việc tạo bốn hình ảnh là đủ tốt vì mặt trước của máy bay có thể hướng về bên trái hoặc bên phải:

Hãy nhớ rằng việc lật là ngẫu nhiên (đôi khi bạn nhận được cả bốn hình ảnh gốc và đôi khi bạn nhận được những hình ảnh được lật theo chiều ngang). Có khả năng bốn hình ảnh trên đều giống nhau. Nếu điều đó xảy ra, chỉ cần chạy lại khối mã đó.

Lật dọc

Giống như lật ngang, bạn cũng có thể thực hiện lật dọc:

datagen = ImageDataGenerator(dọc_flip=Đúng)
train_generator = datagen.flow(images_data, batch_size=1)
hàng = 2
cột = 2
fig, axes = plt.subplots(hàng,cột)
cho r trong phạm vi (hàng):
cho c trong phạm vi (cột):
image_batch = train_generator.next()
hình ảnh = image_batch[0].astype('uint8')
trục[r,c].imshow(hình ảnh)
fig.set_size_inches(15,10)

Trong trường hợp máy bay, việc lật ngược máy bay của chúng ta có thể không có nhiều ý nghĩa! Nếu bạn đang cố gắng thực hiện nhận dạng hình ảnh, rất có thể hình ảnh mặt phẳng của bạn là thẳng đứng và do đó việc đào tạo mô hình của bạn để nhận biết các mặt phẳng lộn ngược có thể không quá phổ biến. Đối với các trường hợp khác, việc lật dọc có rất nhiều ý nghĩa.

Rotation

Xoay, như tên của nó, sẽ xoay hình ảnh của bạn. Điều này sẽ rất hữu ích cho hình ảnh máy bay của chúng tôi. Đoạn mã sau đây ngẫu nhiên xoay hình ảnh lên tới 50 độ:

datagen = ImageDataGenerator(vòng quay_range=50)
train_generator = datagen.flow(images_data)
hàng = 5
cột = 4
fig, axes = plt.subplots(hàng,cột)
cho r trong phạm vi (hàng):
cho c trong phạm vi (cột):
image_batch = train_generator.next()
hình ảnh = image_batch[0].astype('uint8')
trục[r,c].imshow(hình ảnh)
fig.set_size_inches(15,10)

Với chế độ quay, đầu ra hiển thị máy bay ở các vị trí khác nhau - mô phỏng vị trí cất cánh và hạ cánh:

độ sáng

Một kỹ thuật tăng cường khác là điều chỉnh độ sáng của hình ảnh. Đoạn mã sau đặt một loạt giá trị thay đổi độ sáng:

datagen = ImageDataGenerator(độ sáng_range=[0.15,2.0])
train_generator = datagen.flow(images_data, batch_size=1)
hàng = 5
cột = 4
fig, axes = plt.subplots(hàng,cột)
cho r trong phạm vi (hàng):
cho c trong phạm vi (cột):
image_batch = train_generator.next()
hình ảnh = image_batch[0].astype('uint8')
trục[r,c].imshow(hình ảnh)
fig.set_size_inches(15,10)

Đầu ra chứa một loạt hình ảnh có độ sáng khác nhau:

Phóng to

Bạn cũng có thể phóng to hoặc thu nhỏ hình ảnh:

datagen = ImageDataGenerator(zoom_range=[5,0.5])
train_generator = datagen.flow(images_data, batch_size=1)
hàng = 5
cột = 4
fig, axes = plt.subplots(hàng,cột)
cho r trong phạm vi (hàng):
cho c trong phạm vi (cột):
image_batch = train_generator.next()
hình ảnh = image_batch[0].astype('uint8')
trục[r,c].imshow(hình ảnh)
fig.set_size_inches(15,10)

Đầu ra hiển thị hình ảnh ở các tỷ lệ thu phóng khác nhau:

Lưu ý rằng việc thu phóng hình ảnh sẽ làm thay đổi tỷ lệ khung hình của hình ảnh.

Kết hợp tất cả các tăng cường

Tất nhiên, tất cả các kỹ thuật tăng cường khác nhau mà tôi đã thảo luận cho đến nay đều có thể được kết hợp:

datagen = ImageDataGenerator(width_shift_range=0.2,
chiều cao_shift_range=0.2,
Horizontal_flip=Đúng,
vòng_range=50,
độ sáng_range=[0.15,2.0],
zoom_range=[5,0.5]
)
train_generator = datagen.flow(images_data, batch_size=1)hàng = 8
cột = 8
fig, axes = plt.subplots(hàng,cột)
cho r trong phạm vi (hàng):
cho c trong phạm vi (cột):
image_batch = train_generator.next()
hình ảnh = image_batch[0].astype('uint8')
trục[r,c].imshow(hình ảnh)
fig.set_size_inches(15,10)

Lưu ý rằng tôi đã bỏ qua thao tác lật dọc vì nó không có ý nghĩa gì trong ví dụ của chúng ta.

Đầu ra bây giờ hiển thị hình ảnh với các mức tăng cường khác nhau được áp dụng:

Các phần trước đã trình bày những kiến ​​thức cơ bản về tăng cường dữ liệu hình ảnh và cách áp dụng nó cho một hình ảnh. Trong deep learning, chúng ta thường xử lý một tập hợp các hình ảnh. Vì vậy, bây giờ chúng ta hãy xem cách tăng cường hình ảnh có thể được áp dụng cho một tập hợp hình ảnh. Để minh họa, tôi giả sử rằng trong thư mục chứa Notebook Jupyter của bạn, bạn có một Trái cây thư mục và các thư mục con sau:

Trái cây
|__chuối
|__chuối1.jpg
|__chuối2.jpg
|__chuối3.jpg
|__ ...
|__quả sầu riêng
|__sầu riêng1.jpg
|__sầu riêng2.jpg
|__sầu riêng3.jpg
|__ ...
|__quả cam
|__orange1.jpg
|__orange2.jpg
|__orange3.jpg
|__ ...
|__quả dâu
|__dâu1.jpg
|__dâu2.jpg
|__dâu3.jpg
|__ ...

Mỗi thư mục con chứa một tập hợp các hình ảnh. Ví dụ, chuối thư mục chứa một số hình ảnh có tên chuối1.jpg, chuối2.jpg, và như thế. Tên của các thư mục con sẽ đóng vai trò là nhãn cho các hình ảnh khác nhau. Điều này có nghĩa là tất cả các tập tin trong chuối thư mục chứa hình ảnh quả chuối, v.v.

Để tải một loạt ảnh từ đĩa, bây giờ bạn gọi phương thức flow_from_directory() phương pháp của ImageDataGenerator ví dụ thay vì flow() phương thức (để tải hình ảnh từ bộ nhớ):

train_datagen = ImageDataGenerator(
Horizontal_flip=Đúng,
dọc_flip=Đúng,
vòng_range=50,
)
batch_size = 8tàu_máy phát điện = train_datagen.flow_from_directory(
'./Trái cây',
target_size=(224,224),
color_mode='rgb',
batch_size=kích thước lô,
class_mode='phân loại',
xáo trộn=Đúng)

Hãy quan sát rằng bây giờ tôi đã đặt batch_size đến 8. Bạn sẽ sớm thấy việc sử dụng kích thước lô.

Sử dụng trình vòng lặp được trả về, tôi có thể tìm thấy nhãn cho các loại trái cây khác nhau (chuối, sầu riêng, cam và dâu tây):

class_dictionary = train_generator.class_indices#---tạo một từ điển các nhãn---
class_dictionary = { value:key cho khóa,giá trị trong
class_dictionary.items()}
#---chuyển đổi từ điển thành một danh sách---
class_list = [giá trị cho _,giá trị trong class_dictionary.items()]
in(class_list)

Bạn sẽ thấy đầu ra sau:

Tìm thấy 54 hình ảnh thuộc 4 lớp.
['chuối', 'sầu riêng', 'cam', 'dâu']

Tổng cộng có tổng cộng 54 hình ảnh trong 4 thư mục. Ngoài ra, class_list biến chứa danh sách các loại trái cây.

Bây giờ tôi sẽ in ra tập hợp các hình ảnh tăng cường được tạo bởi ImageDataGenerator lớp học. Tôi sẽ tùy ý đặt các hàng thành 10 và với mỗi hàng, tôi muốn in ra lô hình ảnh được trả về (trong ví dụ này là 8):

hàng = 10fig, axes = plt.subplots(rows,batch_size)cho r trong phạm vi (hàng):    
#---lấy hàng loạt hình ảnh được tăng cường---
image_batch = train_generator.next()
#---lấy số ảnh trả về---
số lượng hình ảnh = image_batch[0].shape[0]

cho c trong phạm vi (image_count):
#---chuyển đổi sang số nguyên không dấu để xem---
hình ảnh = image_batch[0][c].astype('uint8')

#---hiển thị hình ảnh---
trục[r,c].imshow(hình ảnh)

#---hiển thị nhãn của hình ảnh---
trục[r,c].title.set_text(
class_list[np.argmax(image_batch[1][c])])
#---ẩn dấu x và y---
trục[r,c].set_xticks([])
trục[r,c].set_yticks([])
fig.set_size_inches(15,18)

Kể từ khi batch_size hiện được đặt thành 8 (và không còn là 1), train_generator.next() phương pháp sẽ trả lại cho bạn một hàng loạt trong số tám hình ảnh được tăng cường mỗi khi bạn gọi nó. Số lượng hình ảnh được trả về dựa trên batch_size mà bạn đã đặt trước đó trong flow_from_directory() phương pháp:

train_generator = train_datagen.flow_from_directory(
'./Trái cây',
target_size=(224,224),
color_mode='rgb',
batch_size=kích thước lô, # kích thước lô = 8
class_mode='phân loại',
xáo trộn=Đúng)

Giá trị của image_batch biến (được trả về bởi next() phương thức) là một bộ gồm hai phần tử:

  • Phần tử đầu tiên (image_batch[0]) là một mảng batch_size hình ảnh (mảng 4D)
  • Phần tử thứ hai (image_batch[1]) chứa nhãn cho hình ảnh

Đoạn mã trên tạo ra kết quả đầu ra sau:

Lưu ý rằng ở hàng thứ bảy, có hai biểu đồ trống không có hình ảnh. Hãy nhớ lại rằng có tổng cộng 54 hình ảnh trong bộ hình ảnh và vì mỗi lô trả về 8 hình ảnh (mỗi hàng), bảy hàng đầu tiên sẽ hiển thị tổng cộng 54 hình ảnh (8×6 + 6). Hình sau đây cho thấy rõ:

Lưu ý rằng bạn có thể thiết lập rows đến bất kỳ số nào và ImageDataGenerator lớp sẽ tiếp tục tạo ra những hình ảnh tăng cường mới cho bạn.

Xây dựng mô hình sử dụng phương pháp học chuyển giao

Bây giờ bạn đã biết cách sử dụng ImageDataGenerator để tải các tập hợp hình ảnh từ đĩa để tăng cường. Nhưng làm thế nào để bạn sử dụng nó để đào tạo? Đoạn mã sau đây cho thấy cách xây dựng mô hình deep learning bằng cách sử dụng học chuyển.

Học chuyển là một phương pháp học máy trong đó mô hình được phát triển cho một nhiệm vụ được sử dụng lại làm điểm bắt đầu cho mô hình của nhiệm vụ thứ hai. Học chuyển tiếp giúp giảm lượng thời gian bạn cần dành cho việc đào tạo.

từ mô hình nhập tensorflow.keras.models
từ tensorflow.keras.applications nhập VGG16
từ tensorflow.keras.layers nhập Dense, GlobalAveragePooling2D
#---số quả---
NO_CLASSES = max(train_generator.class_indices.values()) + 1
#---tải mô hình VGG16 làm mô hình cơ sở để đào tạo---
base_model = VGG16(include_top=False, input_shape=(224, 224, 3))
#---thêm các lớp của riêng chúng ta---
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024,activation='relu')(x) # thêm các lớp dày đặc để
# mà mô hình có thể
# học phức tạp hơn
# chức năng và
# phân loại tốt hơn
# kết quả.
x = Dày đặc(1024,activation='relu')(x) # dày đặc lớp 2
x = Dày đặc(512,activation='relu')(x) # dày đặc lớp 3
preds = Dày đặc(NO_CLASSES,
kích hoạt='softmax')(x) # lớp cuối cùng với
# kích hoạt softmax
#---tạo một mô hình mới với mô hình gốc của mô hình cơ sở
# đầu vào và đầu ra của mô hình mới---
model = Model (đầu vào = base_model.input, đầu ra = preds)
#---không huấn luyện 19 lớp đầu tiên - 0..18---
cho lớp trong model.layers[:19]:
layer.trainable=Sai
#---huấn luyện các lớp còn lại - 19 trở đi---
cho lớp trong model.layers[19:]:
layer.trainable=Đúng

#---biên dịch mô hình---
model.compile(optimizer='Adam',
loss='categorical_crossentropy',
số liệu=['độ chính xác'])

Việc giải thích cách thức hoạt động của học chuyển giao nằm ngoài phạm vi của bài viết này. Tôi sẽ để nó cho một bài viết khác.

Sử dụng hình ảnh được tạo để đào tạo

Để sử dụng hình ảnh tăng cường cho việc đào tạo, hãy vượt qua train_generator vào fit() phương pháp của mô hình:

#---đào tạo người mẫu---
step_size_train = train_generator.n // train_generator.batch_size
model.fit(tàu_máy phát điện,
step_per_epoch=step_size_train,
kỷ nguyên=15)

Sản phẩm steps_per_epoch Về cơ bản, tham số có nghĩa là có bao nhiêu bước trong một kỷ nguyên - nó phụ thuộc vào số lượng hình ảnh bạn có và kích thước lô được xác định trước đó. Nếu bạn đặt con số này ở mức cao thì bạn đang thực hiện quá trình luyện tập lặp đi lặp lại. Bạn nên đặt nó dựa trên công thức này:

số lượng hình ảnh/kích thước lô

Trong ví dụ của chúng tôi, chúng tôi có tổng cộng 54 hình ảnh. Và vì vậy trong mỗi thời đại, ImageDataGenerator lớp sẽ chuyển đổi tất cả 54 hình ảnh để đào tạo. Trong mỗi thời đại, mô hình sẽ có các biến thể hình ảnh khác nhau. Nếu bạn có 15 kỷ nguyên thì tổng cộng 15×54 biến thể của hình ảnh sẽ được tạo và đưa vào mô hình đào tạo.

Sản phẩm ImageDataGenerator lớp cho phép mô hình của bạn nhận được các biến thể mới của hình ảnh ở mỗi kỷ nguyên. Nhưng hãy nhớ rằng nó chỉ trả về những hình ảnh đã được chuyển đổi và không thêm nó vào tập hợp hình ảnh mà bạn có.

Tôi hy vọng bài viết này đã cung cấp cho bạn ý tưởng hay về việc tăng cường dữ liệu hình ảnh là gì và tại sao bạn cần chúng trong quá trình đào tạo các mô hình học sâu của mình. Cụ thể, tôi đã trình diễn nó bằng mô-đun Keras trong thư viện TensorFlow.

Tăng cường dữ liệu hình ảnh cho Deep Learning được xuất bản lại từ nguồn https://towardsdatascience.com/image-data-augmentation-for-deep-learning-77a87fabd2bf?source=rss—-7f60cf5620c9—4 qua https://towardsdatascience.com/feed

<!–

->

Dấu thời gian:

Thêm từ Tư vấn chuỗi khối