如果深度學習是一種超能力,那麼將理論從論文轉化為可用的程式碼就是一種超能力。

作者:Bipin Krishnan P

編譯:ronghuaiyang

本文授權轉載自:AI公園

導讀

如果深度學習是一種超能力,那麼將理論從論文轉化為可用的程式碼就是一種超能力。

如何將深度學習研究論文實現為程式碼的幾個要點

為什麼要去復現機器學習研究論文?

正如我所說的,能夠將一篇論文轉換成程式碼絕對是一種超超能力,尤其是在像機器學習這樣每天都在快速發展的領域。

大多數研究論文來自大型科技公司或大學裡的人,他們可能是博士,也可能是研究前沿技術的人。

還有什麼比復現這些頂尖專業人士的研究成果更酷的呢?另一件需要注意的事情是,行業中對這些能夠將研究論文進行程式碼復現的人需求量很大。

一旦你掌握了撰寫研究論文的竅門,你就會處於與這些研究人員同等的地位。

這些研究人員也是透過閱讀和復現研究論文的練習獲得了這些技能。

我是如何來閱讀和對論文進行復現的?

你可能會說,“嗯,我對深度學習演算法有一個大致的瞭解,像全連線網路,卷積神經網路,迴圈神經網路,但問題是,我想開發SOTA(最新的)語音克隆AI,但我對語音克隆一無所知:(”。

好吧,這裡是你的答案,我的方法的一些部分取自“Andrew Ng關於閱讀論文的建議”:

https://www。

youtube。com/watch?

v=733m6qBH-jI&list=PLoROMvodv4rOABXSygHTsbvUz4G_YQhOb&index=8

如果你想了解一個特定的主題:

收集與特定主題相關的5-6篇論文(你可以透過arxiv或類似的網站找到與某個主題相關的論文)。

不要把每一篇論文完整讀完,而是瀏覽所有的論文,然後挑一篇你感興趣的,或者如果你心裡有一篇特別的論文,那就挑一這篇。

仔細閱讀摘要,從高層次上理解其中的思想,看看你的興趣是否還在繼續,如果還在,那就繼續瀏覽圖片,看看你是否能對論文內容做出假設。

現在,逐行仔細閱讀引言,因為論文所包含的大部分內容將在這裡用最簡單的方式和最小的數學來解釋。

如果你願意,你可以跳過第一輪的數學方公式,但是不要跳過那些有熟悉的希臘字母的數學公式。

在任何情況下,如果你陷入了困境或某些詞讓你迷惑不解,不要猶豫,去google 吧,沒有人生來什麼都懂。

在完成第一關之後,你將處於一種對論文試圖證明或改進的地方有一個高層次的理解的狀態。

在第二步中,嘗試理解本文中的幾乎所有內容,如果遇到任何虛擬碼,嘗試將其轉換為你選擇的python庫(PyTorch、TensorFlow……)

你可以閱讀更多的論文,並透過閱讀每篇論文的參考資料部分來更好地瞭解該領域。

這裡是一些高效理解論文的小技巧:

如果你是研究論文的初學者,最好在閱讀論文之前閱讀一些與該主題/研究論文相關的部落格文章和影片。這使你的工作更容易。

在復現論文時,一定要做筆記,並把重要的地方圈出來,以方便做參考。

如果你是研究論文實現的新手,並且在任何地方遇到了困難,那麼嘗試一下開源實現並看看其他人是如何做到這一點的,這不是一個壞主意。

注意

: 不要把第三點當成常規操作,因為這會導致你的學習曲線會下降,你會過擬合。

你應該發展自己的閱讀和實現論文的方法,這隻有透過開始才有可能,所以上面的步驟將幫助你開始。

Andrew Ng表示,如果你在一個主題上能讀

5 - 10篇論文

,比如語音克隆,你會在實現的時候有一個較好的狀態, 如果你讀了

50 - 100篇論文

,那在這個主題上,你可以進行研究或做前沿技術的研發。

我們來討論一篇論文

高層次的概要

現在,你已經瞭解瞭如何閱讀論文,讓我們閱讀併為自己實現一篇論文。

我們將研究Ian Goodfellow的論文 ——

生成對抗網路

(GAN),並使用PyTorch實現同樣的功能。

論文摘要中對論文內容進行了詳細的概述。

摘要告訴我們,研究人員提出了一個包含兩種神經網路的新框架,它們被稱為“生成器”和“判別器”。

不要被名字弄懵,它們只是兩個神經網路的名字。但在摘要部分要注意的主要一點的是,上面提到的生成器和判別器會相互競爭。

好了,讓我來講清楚一點。

讓我們以用GANs生成不存在的新人臉為例。

該發生器生成與真實影象尺寸(H×W×C)相同的人臉,並將其餵給判別器,判別器判斷該影象是由發生器生成的偽影象還是真實的人臉。

現在你可能會有一個問題,“嗯,這個判別器是如何辨別真假影象的?”,下面就是你的答案:

判別影象是否是真實的是一個分類問題,也就是說,判別器必須分辨影象是真實的還是假的(0或1)。所以我們可以像訓練狗和貓分類卷積神經網路那樣來訓練判別器,而本文中用的是全連線的網路。

DCGAN是另一種型別的GAN,使用卷積神經網路代替全連線網路會有更好的結果。所以我們訓練判別器的方式是將影象輸入判別器中,輸出0或1,也就是說,假的或真的。

當我們訓練我們的判別器時,我們將把由生成器生成的影象傳遞給判別器,並分類它是真的還是假的。生成器調整它所有的權值,直到它能夠欺騙分類器預測生成的影象是真實的。

我們將給生成器一個隨機機率分佈(一個隨機張量),生成器的職責是改變這個機率分佈,以匹配真實影象的機率分佈。

這些是我們在執行程式碼時應該遵循的步驟:

→載入包含真實影象的資料集。

→建立一個二維隨機張量(假資料的機率分佈)。

→建立判別器和生成器模型。

→在真實影象和虛假影象上訓練判別器。

→將假影象的機率分佈送到生成器中,並用判別器測試是否可以區分出這個影象是由生成器生成的虛假影象。

→調整生成器的權值(透過隨機梯度下降)直到判別器無法區分真假影象。

你可能有幾個疑問,但現在沒關係,一旦我們實現了理論程式碼,你會了解它是如何工作的。

損失函式

在我們實現程式碼之前,我們需要一個損失函式,以便我們可以最佳化我們的生成器網路和判別器網路。

該判別器模型是個二分類問題,因此我們使用二元交叉熵損失作為判別器,也可以使用本文討論的自定義損失函式。

本文的損失函式:

[log D(x)] + [log(1−D(G(z)))]

x

→真實影象

z

→假資料或噪聲(隨機張量)

D

→判別模型

G

→生成模型

G(z)

→將假資料或噪聲送到生成器中(輸出是假影象)

D(x)

→將真實影象送到判別器中(輸出是0或1)

D(G(z))

→將假資料送到生成器中,將生成器輸出的影象送到判別器中得到預測(輸出是0或1)

如果你想用論文中的損失函式,讓我來解釋一下:

本文認為,對於判別器,我們需要將上述損失函式最大化。

讓我們看方程的第一部分:

D(x)

輸出0或1,所以,當我們最大化 *log[D(x)]*時,這使得當把真實影象餵給判別器的時候,輸出趨向於1,這正是我們所需要的。

我們再看方程的第二部分:

G(z)

輸出一張影象,和真實的影象具有相同的尺寸,現在將假影象送到判別器*D(G(z))*中,當最大化判別器的輸出的時候,判別器的輸出會趨向於1,此時,當我們最大化[

1 − D(G(z))

]的時候,*D(G(z))*會得到趨向於0的值,這也正是當我們將假影象送到判別器的時候所需要的。

注意

: 你可以在方程上加上一個負號,然後將損失函式轉化為判別器的最小化問題這比最大化更容易。

對於生成器,我們需要最小化上述方程,但本文只考慮方程的第二部分*[log(1−D(G(z)))]*進行最小化。

— 當我們最小化*D(G(z))*時,判別器輸出一個接近於0的值,並且方程的總輸出接近於1,這就是我們的生成器想要達到的,當從生成器得到假影象時,欺騙鑑別器預測1(真實)。

好了,我們開始寫程式碼!

我已經在谷歌colab中完成了程式碼實現,你試試在谷歌colab或jupyter中寫程式碼。

1、匯入所需的庫—

import

torch

from

torch

import

nn

from

torch

import

optim

from

torchvision。transforms

import

transforms

import

numpy

as

np

from

PIL

import

Image

import

matplotlib。pyplot

as

plt

from

tqdm。notebook

import

tqdm

import

warnings

warnings

filterwarnings

“ignore”

2、我們將使用一個單一的影象作為真實的影象,以更快的訓練和得到結果,所以影象生成的生成器將類似於這個影象,你也可以使用一組影象的資料,這一切由你。

我們將使用

PIL library

將影象載入為PIL image,然後使用

torchvision transforms

調整大小並將影象轉換為張量,然後建立大小為(1×100)的偽噪聲來生成影象。

transform = transforms。Compose([

transforms。Resize((32, 32)),

transforms。ToTensor()

])

flat_img = 3072 #32×32×3 ——size of flattened image

img = Image。open(‘truck。jpeg’)

real_img = transform(img)

torch。manual_seed(2)

fake_img = torch。rand(1, 100)

plt。imshow(np。transpose(real_img。numpy(), (1, 2, 0)))

print(real_img。size())

3、建立一個判別器模型,它是一個全連線的神經網路,接收真實影象或偽影象,輸出0或1。

class Discriminator(nn。Module):

def __init__(self):

super()。__init__()

self。linear = nn。Sequential(

nn。Linear(flat_img, 10000),

nn。ReLU(),

nn。Linear(10000, 1),

nn。Sigmoid()

def forward(self, img):

img = img。view(1, -1)

out = self。linear(img)

return out

4、建立一個生成器模型,它也是一個全連線的網路,接受隨機噪聲並輸出一個與真實影象大小相同的影象張量。

class Generator(nn。Module):

def __init__(self):

super()。__init__()

self。linear = nn。Sequential(

nn。Linear(100, 10000),

nn。LeakyReLU(),

nn。Linear(10000, 4000),

nn。LeakyReLU(),

nn。Linear(4000, flat_img)

def forward(self, latent_space):

latent_space = latent_space。view(1, -1)

out = self。linear(latent_space)

return out

5、初始化模型,最佳化器和損失函式,然後將它們移動到所需的裝置(cuda或cpu)。我們在判別器中使用二元交叉熵損失,並對生成器使用本文中討論的損失函式

log(1 - D(G(z))

device = ‘cuda:0’ if torch。cuda。is_available() else ‘cpu’

discr = Discriminator()。to(device)

gen = Generator()。to(device)

opt_d = optim。SGD(discr。parameters(), lr=0。001, momentum=0。9)

opt_g = optim。SGD(gen。parameters(), lr=0。001, momentum=0。9)

criterion = nn。BCELoss()

6、現在我們對模型進行訓練,整個GAN被訓練500個大的epoch,判別器先訓練4個epoch,然後生成器再訓練3個epoch。

epochs = 500

discr_e = 4

gen_e = 3

#whole model training starts here

for epoch in tqdm(range(epochs), total=epochs):

#discriminator training

for k in range(discr_e):

opt_d。zero_grad()

out_d1 = discr(real_img。to(device))

#loss for real image

loss_d1 = criterion(out_d1, torch。ones((1, 1))。to(device))

loss_d1。backward()

out_d2 = gen(fake_img。to(device))。detach()

#loss for fake image

loss_d2 = criterion(discr(out_d2。to(device)), torch。zeros((1, 1))。to(device))

loss_d2。backward()

opt_d。step()

#generator training

for i in range(gen_e):

opt_g。zero_grad()

out_g = gen(fake_img。to(device))

#Binary cross entropy loss

#loss_g = criterion(discr(out_g。to(device)), torch。ones(1, 1)。to(device))

#——Loss function in the GAN paper

#[log(1 - D(G(z)))]

loss_g = torch。log(1。0 - (discr(out_g。to(device))))

loss_g。backward()

opt_g。step()

7、將生成的影象與真實影象進行比較。你可以調整學習率,動量,epochs以及生成器和判別器中的層以得到更好的結果。

如何將深度學習研究論文實現為程式碼的幾個要點

最後的思考

生成的影象可能解析度不是很高,因為本文只是整個生成模型的開始。如果你仍然在堅持,你可以繼續閱讀DCGANs或其他論文:

https://

github。com/nightrome/re

ally-awesome-gan

,並實現看看那些了不起的結果,但請記住本文是這些論文的基礎。

英文原文:

https://

towardsdatascience。com/

converting-deep-learning-research-papers-to-code-f-f38bbd87352f

另外強烈推薦閱讀,Amusi 整理過的最全資料系列如下:

GitHub:深度學習最全資料集錦

GitHub:影象分類最全資料集錦

GitHub:目標檢測最全論文集錦

GitHub:影象分割最全資料集錦

GitHub:目標跟蹤最全資料集錦

GitHub:人群密度估計最全資料集錦

GitHub:車道線檢測最全資料集錦

GitHub:TensorFlow最全資料集錦

GitHub:Anchor-free目標檢測最全資料集錦

GitHub:資料增廣最全資料集錦

GitHub:語義分割最全資料集錦

GitHub:人群計數最全資料集錦

推薦大家關注計算機視覺論文速遞知乎專欄和CVer微信公眾號,可以快速瞭解到最新優質的CV論文。

推薦閱讀

300+篇CVPR 2020程式碼開源的論文,全在這裡了!

955 不加班的公司名單:955。WLB

北京提供計算機視覺CV演算法崗的公司名單

上海提供計算機視覺CV演算法崗的公司名單

大盤點 | 十大即插即用的漲點神器!

YOLOv5被禁用!Kaggle全球小麥檢測競賽結果惹爭議

CVPR 引用量最高的10篇論文!何愷明ResNet登頂,YOLO佔據兩席!

ICCV 引用量最高的10篇論文!何愷明兩篇一作論文:Mask R-CNN和PReLU

ECCV 引用量最高的10篇論文!SSD登頂!何愷明ResNet改進版位居第二

OpenCV4。4剛剛釋出!支援YOLOv4、EfficientDet檢測模型,SIFT移至主庫!

目標檢測四大開源神器Detectron2/mmDetection/darknet/SimpleDet

超越YOLOv4!PP-YOLO:更快更好的目標檢測網路

ECCV 2020 放榜!一文看盡10篇論文的開源專案(檢測/GAN/SR等方向)

有人手寫實現李航《統計學習方法》書中全部演算法

大神沒交棒,但YOLOv5來了!

大神接棒,YOLOv4來了!

YOLOv4-Tiny來了!371 FPS!

ResNet最強改進版來了!ResNeSt:Split-Attention Networks

周志華教授:如何做研究與寫論文