Kiến trúc của Pix2Pix cũng bao gồm 2 mô hình mạng là generator và discriminator. Generator có tác dụng sinh ảnh giả để đánh lừa discriminator và discriminator có mục tiêu phân biệt giữa ảnh thật và ảnh giả.
Mạng Generator
Đầu vào của generator là một bức ảnh nguồn (source image). Sau đó bức ảnh được truyền vào một kiến trúc mạng tích chập để trích lọc đặc trưng thông qua quá trình down sampling. Ở quá trình này, đầu ra ở các lớp sẽ có kích thước giảm dần thông qua tích chập 2 chiều. Trong khi đó mạng giải chập (Deconvolution) làm nhiệm vụ ngược lại là biến đổi đặc trưng thành ảnh đích (target image) thông qua quá trình up sampling bằng các lớp chuyên biệt như transposed Convolution, Dilation Convolution, Upsampling 2D. Quá trình up sampling sẽ gia tăng dần kích thước đầu ra và kết quả trả ra là một bức ảnh đích mang nhãn giả.
Kiến trúc down sampling và upsampling trong bài toán image-to-image
translation. Đây cũng chính là kiến trúc chung của generator trong Pix2Pix GAN.
Đầu vào của Generator là ảnh vẽ còn đầu ra là ảnh màu nên kiến trúc cũng gần giống với U-Net [10], dựa trên kiến trúc U-Net được phát triển bởi Olaf Ronneberger và các cộng sự để dùng cho image segmentation trong y học để khởi tạo generator.
Kiến trúc có hai phần đối xứng nhau được gọi là encoder (phần bên trái) và decoder (phần bên phải). Các lớp ở nhánh bên trái (phần encoder) sẽ
được concatenate trực tiếp vào các lớp ở nhánh bên phải (phần decoder) có
cùng kích thước. Kết nối này được gọi là kết nối tắt (skip connection) nhằm bổ sung thêm thông tin và gia tăng độ chính xác
Hình 2.7: Generator pix2pix
Ngoài ra còn có thể sử dụng ý tưởng của resnet (densenet) để cộng (nối) các lớp tương ứng ở encoder với decoder.
Hình 2.8: Mô hình generator pix2pix
Discriminator
Đầu vào của discriminator là một cặp ảnh x,y. Trong đó x là ảnh nguồn
(source) đầu vào và y là ảnh đích (target) được sinh ra từ generator hoặc được
lấy từ tập huấn luyện. Hai ảnh x,y có cùng kích thước và sẽ được concatenate
với nhau trước khi truyền vào mô hình discriminator. Cặp ảnh sẽ có nhãn là thật (real) nếu ảnh y được lấy từ tập đào tạo và trái lại khi y được sinh ra từ
generator thì cặp ảnh x,y nó sẽ mang nhãn giả (fake).
Hình 2.9: Mô hình discriminator pix2pix
ảnh vẽ nên còn được gọi là condition GAN (cGAN), tức là ảnh đầu ra phụ thuộc vào ảnh đầu vào. Việc cho cả ảnh đầu vào giúp discriminator dễ phân biệt hơn ảnh nào là generator sinh ra và ảnh nào trong tập dữ liệu.
Hai ảnh đầu vào sẽ được nối với nhau sau đó thực hiện các lớp trong ConvNet và ra output 30*30*1, cách thiết kế mạng discrimintor như vậy gọi là PatchGAN. Nội dung tiếp theo, chúng ta sẽ tìm hiểu về kiến trúc PatchGan.
PatchGAN
PatchGAN là một kiến trúc mà có Discriminator dựa trên các vùng
nhận thức (receptive field). Nó sẽ maping mỗi một pixel ở đầu ra từ một vùng diện tích hình vuông nằm trên đầu vào (hay còn gọi là patch).
Một PatchGAN với kích thước 70 x 70 có nghĩa rằng mỗi một đầu ra sẽ
được map tới một patch kích thước 70 x 70. Mô hình sẽ phân loại các
patch 70 x 70 là thật hay giả.
Kết quả của PatchGAN sẽ có đầu ra là một feature map hình vuông gồm tập hợp các xác suất mà mỗi một xác suất tương ứng với khả năng một patch kích thước 70 x 70 rơi vào thật hoặc giả. Xác suất cho toàn bộ hình ảnh đầu vào là thật hoặc giả có thể được tính bằng trung bình cộng của toàn bộ các xác suất trên toàn bộ patches.
Về bản chất của PatchGAN thì vẫn là một kiến trúc mạng CNN gồm nhiều lớp CNN liên tiếp nhau, nhưng chúng ta không thực hiện flatten ở gần cuối để truyền qua các lớp fully connected. Mà thay vào đó tính toán ra feature map xác suât trên từng patch như đã nêu ở trên. Cách tính như vậy sẽ mang lại hiệu quả nếu áp dụng trên các patch có kích thước lớn vì có vùng nhận thức (receptive field) lớn hơn. Kết quả xác suất trung bình của nhiều patches cũng sẽ chuẩn xác hơn.
Hình 2.10: Giả sử hình ảnh đƣợc chia thành k×k patches
Trên mỗi patch ta dự báo một xác suất ảnh rơi vào ảnh thật. Xác suất để toàn bộ bức ảnh là thật sẽ là trung bình cộng xác suất của toàn bộ các patches. Tiếp theo ta sẽ cùng tìm hiểu kiến trúc CNN được áp dụng trên một patch.
Kiến trúc các lớp của PatchGAN cũng bao gồm 4 lớp CNN theo thứ tự: I -> C1 -> C2 -> C3 -> C4 -> O. Dựa vào kích thước output shape của một lớp ta có thể xác định được kích thước input shape của lớp liền trước nó. Thật vậy:
Theo công thức tính kích thước đầu ra của tích chập 2 chiều theo kích thước
đầu vào , kích thước filter F, stride S và padding P ta có:
Như vậy kích thước của receptive field được tính dựa
trên sẽ là:
( )
Chúng ta sẽ lần ngược theo công thức trên để suy ra kích thước của từng lớp. Thứ tự lần ngược O -> C4 -> C3 -> C2 -> C1 -> I.
Tại lớp đầu ra O.
Suy ra kích thước của C4: ( )
Tại lớp C4.
Suy ra kích thước của C3: ( )
Tại lớp C3.
Suy ra kích thước của C2: ( )
Tại lớp C2.
Suy ra kích thước của C1: ( )
Tại lớp C1.
Suy ra kích thước của I: ( )
Hình 2.11: Sơ đồ tổng quát kiến trúc các lớp CNN áp dụng trên một patch 70x70 của PatchGAN.
2.5.3 Hàm tối ưu
Hàm tối ưu (Loss function) của Pix2Pix là một hàm dạng binary cross
entropy có dạng như sau:
( ) [ 𝑜 (𝑥 )]
⏟
log probability that D predict {x, y is real
[ 𝑜 ( (𝑥 (𝑥 )))]
⏟
Nó hoàn toàn giống với hàm tối ưu của GAN đã giới thiệu ở trước đó.
Chỉ khác ở đầu vào là một cặp ảnh x,y thay vì chỉ là x.
Quá trình huấn luyện của chúng ta sẽ là một quá trình huấn luyện đồng thời trên cả Generator và Discriminator. Discriminator sẽ tìm cách phân loại ảnh thật và giả chuẩn xác nhất nên giá trị hàm tối ưu của nó là hàm cross
entropy phải càng nhỏ càng tốt. Tức là chúng ta cần tìm 𝑚 𝑥 ( )
Bên cạnh đó, trong trường hợp ảnh là giả thì chúng ta cần Generator
sinh ra nó giống với thật nhất, tức là giá trị xác suất (𝑥 (𝑥 )) phải gần 1
nhất có thể. Do đó chúng ta cần tìm 𝑚 ( )
Kết hợp cả hai bài toán tối ưu giữa Generator và Discriminator chúng ta thu được bài toán tối ưu:
𝑚 𝑚 𝑥 ( )
Để kiểm tra tầm quan trọng của điều kiện trong việc phân loại, chúng ta
có một phiên bản không điều kiện bằng cách loại bỏ x khỏi mô hình
discriminator. Khi đó hàm tối ưu sẽ trở thành:
( ) [ 𝑜 ( )]
⏟
log probability that D predict is real
[ 𝑜 ( ( (𝑥 )))]
⏟
log probability D predicts x, z is fake
Có thể hình dung phương pháp này tương đương với việc ta không
truyền vào discriminator một cặp x,y mà chỉ truyền vào y.
Ngoài ra nếu kết hợp giữa hàm tối ưu của GAN với một hàm tối ưu
truyền thống như norm (chuẩn) bậc 1 (L1) hoặc bậc 2 (L2). Khi đó vai trò
phân biệt thật/giả của discriminator không đổi, còn generator ngoài đánh lừa được discriminator thì nó còn phải làm sao sinh ảnh giống với ground truth
(chuẩn) bậc L1 trong hàm tối ưu:
( ) [|| (𝑥 ) || ]
Hàm tối ưu mới:
𝑚 𝑚 𝑥 ( ) ( )
Ở đây λ là một hệ số của hàm tối ưu theo norm (chuẩn) bậc 1, thường được thiết lập rất nhỏ.
2.6. Kết luận chƣơng 2
Qua các nội dung đã trình bày giúp cho chúng tôi có được những kiến thức cơ bản về mô hình GAN như: kiến trúc của mô hình, xây dựng hàm tối ưu, cách huấn luyện mô hình, đồng thời chúng tôi tìm hiểu về mô hình Pix2Pix, một lớp mô hình chuyên biệt cho các tác vụ image-to-image
translation. Từ nghiên cứu nội dung ở chương này, ta có thể xây dựng ứng
CHƢƠNG 3: ỨNG DỤNG GAN TRONG BÀI TOÁN CHUYỂN ĐỔI ẢNH
Trong chương 3, chúng tôi sẽ giới thiệu và phân tích bài toán chuyển đổi ảnh, thu thập dữ liệu, xây dựng chương trình thử nghiệm. Đồng thời trình bày các kết quả của việc đào tạo mô hình trên tập dữ liệu huấn luyện để làm căn cứ đánh giá kết quả thực hiện bài toán.
3.1. Giới thiệu và phân tích bài toán. Phát biểu bài toán: Phát biểu bài toán:
Cho tập ảnh mẫu, từng cặp có một ảnh phác thảo và một ảnh đích. Bài toán đặt ra là, với đầu vào là một ảnh phác thảo, chương trình phải tự sinh ra ảnh đích phù hợp.
Trước hết bài toán image to image là bài toán trong đó đầu vào và đầu ra đều là tấm ảnh. Mục tiêu cuối cùng của bài toán mà chúng tôi nghiên cứu ở đây chính là tạo ra ảnh giày, dép thực từ ảnh phác thảo cho trước.
Chúng ta có tập ảnh mẫu “edges2shoes”. Đây là tập dữ liệu bao gồm
các hình ảnh phác thảo giày, dép và các ảnh màu thật tương ứng của chúng. Sơ lược về bộ dữ liệu bao gồm:
Tập ảnh huấn luyện (Training set): Có 49825 ảnh dùng để học khi huấn luyện.
Tập ảnh kiểm tra (Test set): Có 200 ảnh dùng để kiểm chứng mô hình khi huấn luyện.
Trong đó:
Hình ảnh có tên tệp là chữ số và ở định dạng JPEG. Mỗi hình ảnh có chứa cả hình ảnh giày dép phác thảo ở bên trái và hình ảnh giày dép thực ở
bên phải.
Hình 3.1: Hình ảnh mẫu từ tập dữ liệu
Để giải quyết bài toán này, chúng tôi sử dụng dữ liệu mẫu huấn luyện một mô hình pix2pix để có thể sinh ảnh giả từ ảnh phác thảo phù hợp với ảnh thực trong tập mẫu.
3.2. Xây dựng chƣơng trình thử nghiệm
Tập dữ liệu: Tải xuống bộ dữ liệu tại:
https://people.eecs.berkeley.edu/~tinghuiz/projects/pix2pix/datasets/ed ges2shoes.tar.gz
Để phát triển và đào tạo mô hình Pix2Pix, chúng tôi tiến hành đào tạo đồng thời bộ phân biệt (the discriminator) và bộ tạo (the generator).
Xây dựng bộ phân biệt (the discriminator)
Bộ phân biệt là một mạng nơ-ron phức hợp sâu thực hiện phân loại hình ảnh. Cụ thể là phân loại ảnh có điều kiện. Nó lấy cả ảnh nguồn (ví dụ ảnh phác thảo) và ảnh đích (ví dụ ảnh giày dép thật) làm đầu vào và dự đoán khả năng ảnh đích là thật hay là bản dịch giả của ảnh nguồn.
Để thiết kế bộ phân biệt chúng tôi xác định mối quan hệ giữa một đầu ra của mô hình với số lượng pixel trong hình ảnh đầu vào. Đây được gọi là mô hình PatchGAN và được thiết kế cẩn thận để mỗi dự đoán đầu ra của mô hình ánh xạ tới hình vuông hoặc bản vá 70 × 70 của hình ảnh đầu vào. Lợi ích của cách tiếp cận này là cùng một mô hình có thể được áp dụng cho các hình ảnh đầu vào có kích thước khác nhau.
Để tiến hành đào tạo bộ phân biệt, chúng tôi xây dựng hàm def
Discriminator() để triển khai mô hình phân biệt PatchGAN 70 × 70 theo thiết kế của mô hình. Bộ phân biệt nhận được hai đầu vào: Hình ảnh đầu vào và hình ảnh đích mà nó sẽ được phân loại là thực. Hình ảnh đầu vào và hình ảnh được tạo ra (đầu ra của bộ đào tạo), mà nó sẽ được phân loại là giả mạo.
Bộ phân biệt trong pix2pix là bộ phân loại PatchGAN phức tạp, nó cố
gắng phân loại xem mỗi bản váhình ảnh là thật hay không thật hay. Dựa trên
cấu trúc PatchGAN chúng tôi xác định có những thành phần sau:
(1) Mỗi khối trong bộ phân biệt là: Convolution -> Batch normalization
-> Leaky ReLU.
(2) Hình dạng của đầu ra sau lớp cuối cùng là (batch_size, 30, 30, 1).
(3) Mỗi 30 x 30 bản vá hình ảnh của đầu ra phân loại một 70 x 70 phần
của hình ảnh đầu vào.
Quá trình xây dựng chức năng Discriminator như sau:
Để bắt đầu, chúng tôi xác định bộ khởi tạo trọng lượng lớp tích chập (the convolution layer weight) được lấy mẫu từ một phân phối đồng đều, với giá trị trung bình (mean=0) và độ lệch chuẩn (standard-deviation=0.02.)
Chúng tôi xác định hai lớp đầu vào với kích thước [256,256,3]. Hãy nhớ rằng, bộ phân biệt của chúng tôi là điều kiện trên hình ảnh đầu vào (các cạnh).
Chúng tôi sử dụng hàm tf.concat([inp, tar], axis=-1) để ghép 2 đầu vào này với nhau.
Sau đó, chúng ta có ba khối mẫu xuống (downsample blocks) thông thường, trong đó khối đầu tiên có batchnorm = False. Các lớp Convolution có kernel_size = 4, bắt đầu với 64 bộ lọc (filters). Các bộ lọc này tăng gấp đôi tại mỗi khối mẫu xuống (64-> 128-> 256), dẫn đến kết quả đầu ra là [32, 32, 256].
Chúng tôi tiếp tục xây dựng một lớp zeropadding, lớp đệm mỗi feature map dọc theo cả trục x và y, dẫn đến kết quả đầu ra sẽ là [34,34,256], Điều này được cung cấp thêm cho một khối chuyển đổi (zeropadding layer) có :
Một lớp Conv2D, với kernel_size = 4, 512 bộ lọc (filters) và bước
trượt (stride) là 1, dẫn đến kết quả là [31,31,512]
Sau đó là các lớp Conv2D, Batchnorm và LeakyReLU.
Cuối cùng, chúng ta có thêm một lớp zeropadding nữa và đầu ra của nó được đưa đến lớp Conv2D với kernel_size = 1, stride = 1 và số bộ lọc (filters) là 1 (vì chúng ta chỉ muốn đầu ra 1 kênh).
Tiếp theo, chúng tôi tạo một bản vá (patch) thứ nguyên có kích thước [30, 30, 1]. Ngoài ra, chúng tôi kích hoạt trong lớp này là một hàm sigmoid, tạo ra một xác suất trong phạm vi [0, 1], về khả năng mỗi 1 × 1 từ bản vá 30 × 30 là thật hay giả.
Như vậy, chúng tôi đã xây dựng xong chức năng bộ phân biệt (the discriminator), tiếp theo chúng tôi tiếp tục xây dựng bộ tạo(the generator)
Xây dựng bộ tạo (the generator):
Mô hình bộ tạo phức tạp hơn mô hình phân biệt. Bộ tạo là một mô hình bộ mã hóa-giải mã sử dụng kiến trúc U-Net. Mô hình lấy ảnh nguồn (ví dụ
ảnh giày, dép phác thảo) và tạo ảnh đích (ví dụ ảnh giày, dép thật). Nó thực hiện điều này bằng cách lấy mẫu đầu tiên xuống hoặc mã hóa hình ảnh đầu vào xuống một lớp nút cổ chai, sau đó lấy mẫu hoặc giải mã biểu diễn nút cổ chai thành kích thước của hình ảnh đầu ra. Kiến trúc U-Net có nghĩa là các kết nối bỏ qua được thêm vào giữa các lớp mã hóa và các lớp giải mã tương ứng, tạo thành một hình chữ U.
Để thực hiện mô hình trình tạo bộ mã hóa và giải mã U-Net. Chúng tôi
xây dựng hàm def downsample() để tạo các khối lớp cho bộ mã hóa và
hàm def upsample() để tạo các khối lớp cho bộ giải mã. Chúng tôi xác định: Các chức năng bộ mã hóa (downsample) bao gồm:
Một lớp Conv2D
Một lớp optional BatchNorm
Tiếp theo là chức năng kích hoạt LeakyReLU, với độ dốc ( slope) là 0,2
Các chức năng bộ giải mã (upsample) bao gồm:
Một lớp Conv2DTranspose
Một lớp optional BatchNorm
Một lớp optional Dropout, với drop_probability = 0,5
Tiếp theo là chức năng kích hoạt ReLU, với độ dốc (slope )= 0,2
Trọng số của lớp Convolution trong cả chức năng bộ mã hóa và bộ giải mã được khởi tạo từ phân phối đồng đều, với giá trị trung bình mean=0 và độ lệch chuẩn standard-deviation = 0,02 và không có độ lệch (bias) nào được sử dụng.
Tiếp theo chúng tôi xây dựng UNET Generator, bao gồm một bộ mã hóa (downsample) và giải mã (upsample) dựa trên kết nối bỏ qua. Chúng tôi xác định lớp đầu vào với hình dạng [256,256,3], là hình dạng của hình ảnh mà chúng tôi đã xử lý trước.
Chúng tôi tiến hành xây dựng bộ mã hóa thông qua hàm def
Các lớp bộ mã hóa được xác định là danh sách các lớp trong đó hình ảnh [256, 256, 3] được cung cấp làm đầu vào, được lấy mẫu theo hệ số 2 ở mỗi lần gọi hàm khối mẫu xuống và tổng cộng 8 lần, do đó đạt đến nút cổ chai có kích thước [1, 1, 512].
Tất cả các lớp Conv2D:
Sử dụng kernel_size= 4, với bước trượt (stride) là hai.
Khi đầu vào tại mỗi khối mẫu xuống (downsample block ) được giảm
một nửa (theo chuỗi-chập (strided-convolution)), các feature maps được tăng gấp đôi, bắt đầu từ 64 và tăng lên 512 tại nút cổ chai.
Lớp Batchnorm được sử dụng trong tất cả trừ khối mẫu xuống
(downsample block) đầu tiên.
Chúng tôi tiến hành xây dựng bộ giải mã thông qua hàm def upsample(), như
sau:
Các lớp bộ giải mã được xác định đầu ra có kích thước nút cổ chai [1,1,512] được lấy làm đầu vào, được lấy mẫu (upsampled) thêm theo hệ số 2 tại mỗi khối lấy mẫu ( upsample block). Tổng cộng có 7 lệnh gọi hàm