50行代碼實(shí)現(xiàn)GAN

人生苦短我用GAN

首先聲明一下匙隔,本教程面向入門吃瓜群眾疑苫,大牛可以繞道,閑話不多說捍掺,先方一波廣告撼短。(高級GAN玩法),怎么說挺勿,我越來越感覺到人工智能正在迎來生成模型的時代曲横,以前海量數(shù)據(jù)訓(xùn)練模型的辦法有點(diǎn)揠苗助長,看似效果很好不瓶,實(shí)際上機(jī)器什么卵都沒有學(xué)到(至少從遷移性上看缺少一點(diǎn)味道禾嫉,不過就圖片領(lǐng)域來說另當(dāng)別論,在CV領(lǐng)域監(jiān)督學(xué)習(xí)還是相當(dāng)成功)湃番。
但是問題來了夭织,GAN這么屌這么牛逼,我怎么搞吠撮?怎么入門尊惰?誰帶我?慌了泥兰!

莫慌弄屡,50行代碼你就可以成為無監(jiān)督學(xué)習(xí)大牛

我最討厭那些,嘴里一堆算法鞋诗,算法實(shí)現(xiàn)不出來的人膀捷。因?yàn)槲蚁矚g看到結(jié)果啊削彬!尤其是一些教程全庸,就是將論文,雞巴論文獎那么多有什么用融痛?你碼代碼給我看啊壶笼,我不知道數(shù)據(jù)是什么,不知道輸入維度是什么雁刷,輸出什么覆劈,里面到底發(fā)生了什么變化我怎么學(xué)?這就有點(diǎn)像沛励,典型的在沙漠里教你釣魚责语,在我看來,論文應(yīng)該是最后才去看的東西目派。但是問題在于坤候,你要有一個入門的教程啊。我想這是一個鴻溝企蹭,科研里面白筹,理論和動手的鴻溝徘键。
這篇教程就是引路人了。歡迎加入生成模型隊伍遍蟋。這個教程會一直保持更新,因?yàn)榭萍济刻熳兓媚獪y螟凭,同時我還會加入很多新內(nèi)容虚青,改進(jìn)一些在以后看來是錯誤的說法。

首先螺男,我們廢話不多說了棒厘,直接show you the code:

import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
import matplotlib.pyplot as plt
from scipy import stats


def generate_real_data_distribution(n_dim, num_samples):
    all_data = []
    for i in range(num_samples):
        x = np.random.uniform(0, 8, n_dim)
        y = stats.lognorm.pdf(x, 0.6)
        all_data.append(y)
    all_data = np.array(all_data)
    print('generated data shape: ', all_data.shape)
    return all_data


def batch_inputs(all_data, batch_size=6):
    assert isinstance(all_data, np.ndarray), 'all_data must be numpy array'
    batch_x = all_data[np.random.randint(all_data.shape[0], size=batch_size)]
    return Variable(torch.from_numpy(batch_x).float())


def main():
    # 給generator的噪音維數(shù)
    n_noise_dim = 30
    # 真實(shí)數(shù)據(jù)的維度
    n_real_data_dim = 256
    num_samples = 666
    lr_g = 0.001
    lr_d = 0.03
    batch_size = 6
    epochs = 1000

    real_data = generate_real_data_distribution(n_real_data_dim, num_samples=num_samples)
    print('sample from real data: \n', real_data[: 10])

    g_net = nn.Sequential(
        nn.Linear(n_noise_dim, 128),
        nn.ReLU(),
        nn.Linear(128, n_real_data_dim)
    )

    d_net = nn.Sequential(
        nn.Linear(n_real_data_dim, 128),
        nn.ReLU(),
        nn.Linear(128, 1),
        nn.Sigmoid()
    )

    opt_d = torch.optim.Adam(d_net.parameters(), lr=lr_d)
    opt_g = torch.optim.Adam(g_net.parameters(), lr=lr_g)

    for epoch in range(epochs):
        for i in range(num_samples // batch_size):
            batch_x = batch_inputs(real_data, batch_size)
            batch_noise = Variable(torch.randn(batch_size, n_noise_dim))

            g_data = g_net(batch_noise)

            # 用G判斷兩個輸出分別多大概率是來自真正的畫家
            prob_fake = d_net(g_data)
            prob_real = d_net(batch_x)

            # 很顯然,mean里面的這部分是一個負(fù)值下隧,如果想整體loss變小奢人,必須要變成正直,加一個負(fù)號淆院,否則會越來越大
            d_loss = -torch.mean(torch.log(prob_real) + torch.log(1 - prob_fake))
            # 而g的loss要使得discriminator的prob_fake盡可能小何乎,這樣才能騙過它,因此也要加一個負(fù)號
            g_loss = -torch.mean(torch.log(prob_fake))

            opt_d.zero_grad()
            d_loss.backward(retain_variables=True)
            opt_d.step()

            opt_g.zero_grad()
            g_loss.backward(retain_variables=True)
            opt_g.step()

            print('Epoch: {}, batch: {}, d_loss: {}, g_loss: {}'.format(epoch, i, d_loss.data.numpy()[0],
                                                                        g_loss.data.numpy()[0]))

if __name__ == '__main__':
    main()

這些代碼土辩,總共支救,也就是90行,核心代碼50行拷淘,基本上各墨,比你寫一個其他程序都端,什么紅黑算法启涯,什么排序之類的贬堵。我個人比較喜歡簡約,我很多時候不喜歡太雞巴隆昌的代碼结洼。

直接開始訓(xùn)練吧

這個GAN很簡單黎做,三部分:

  • real data生成,這個real data我們怎么去模擬呢补君?注意這里用的數(shù)據(jù)是二維的引几,不是圖片,圖片是三維的挽铁,二維你可以看成是csv伟桅,或者是序列,在這里面我們每一行叽掘,也就是一個樣本楣铁,是sample自某個分布的數(shù)據(jù),這里用的分布式lognorm更扁;
  • d_net 和 g_net盖腕,這里兩個net都是非常小赫冬,小到爆炸,這如果要是用tensorflow寫就有點(diǎn)蛋疼了溃列,我選擇PyTorch劲厌,一目了然;
  • loss听隐,loss在GAN中非常重要补鼻,是接下來的重點(diǎn)。

OK雅任,一陣復(fù)制粘貼风范,你就可以訓(xùn)練一個GAN,這個GAN用來做什么沪么?就是你隨機(jī)輸入一個噪音硼婿,生成模型將會生成一個和lognorm分布一樣的數(shù)據(jù)。也就是說禽车,生成模型學(xué)到了lognrom分布寇漫。這能說明什么?神經(jīng)網(wǎng)絡(luò)學(xué)到了概率殉摔!用到圖片里面就是猪腕,他知道哪個顏色快可能是什么東西,這也是現(xiàn)在的CycleGAN钦勘, DiscoGAN的原理陋葡。

我吃飯去了

未完待續(xù)...

來了

繼續(xù)剛才的,好像我寫的文章沒有人看啊彻采,傷感腐缤。自己寫自己看吧,哎肛响,我騷味改了一下代碼岭粤,loss函數(shù)部分,之前的寫錯了特笋,我偷一張圖把剃浇。



這個是公式,原始GAN論文里面給的公式猎物,但是毫無疑問虎囚,正如很多人說的那樣,GAN很容易漂移:

Epoch: 47, batch: 66, d_loss: 0.7026655673980713, g_loss: 2.0336945056915283
Epoch: 47, batch: 67, d_loss: 0.41225430369377136, g_loss: 2.1994106769561768
Epoch: 47, batch: 68, d_loss: 0.674636960029602, g_loss: 1.5774009227752686
Epoch: 47, batch: 69, d_loss: 0.5779278874397278, g_loss: 2.2797725200653076
Epoch: 47, batch: 70, d_loss: 0.4029145836830139, g_loss: 2.200833559036255
Epoch: 47, batch: 71, d_loss: 0.7264774441719055, g_loss: 1.5658557415008545
Epoch: 47, batch: 72, d_loss: 0.46858924627304077, g_loss: 2.355680227279663
Epoch: 47, batch: 73, d_loss: 0.6716371774673462, g_loss: 1.7127293348312378
Epoch: 47, batch: 74, d_loss: 0.7237206101417542, g_loss: 1.4458404779434204
Epoch: 47, batch: 75, d_loss: 0.9684935212135315, g_loss: 1.943861961364746
Epoch: 47, batch: 76, d_loss: 0.4705852270126343, g_loss: 2.439894199371338
Epoch: 47, batch: 77, d_loss: 0.4989328980445862, g_loss: 1.5290288925170898
Epoch: 47, batch: 78, d_loss: 0.44530192017555237, g_loss: 2.9254989624023438
Epoch: 47, batch: 79, d_loss: 0.6329593658447266, g_loss: 1.7527830600738525
Epoch: 47, batch: 80, d_loss: 0.42348209023475647, g_loss: 1.856258749961853
Epoch: 47, batch: 81, d_loss: 0.5396828651428223, g_loss: 2.268836498260498
Epoch: 47, batch: 82, d_loss: 0.9727945923805237, g_loss: 1.0528483390808105
Epoch: 47, batch: 83, d_loss: 0.7551510334014893, g_loss: 1.508225917816162
Epoch: 47, batch: 84, d_loss: 2.4204068183898926, g_loss: 1.5375216007232666
Epoch: 47, batch: 85, d_loss: 1.517686128616333, g_loss: 0.6334291100502014
Epoch: 47, batch: 86, d_loss: inf, g_loss: 0.7990849614143372
Epoch: 47, batch: 87, d_loss: nan, g_loss: nan
Epoch: 47, batch: 88, d_loss: nan, g_loss: nan
Epoch: 47, batch: 89, d_loss: nan, g_loss: nan
Epoch: 47, batch: 90, d_loss: nan, g_loss: nan
Epoch: 47, batch: 91, d_loss: nan, g_loss: nan

你如果train一下的話會發(fā)現(xiàn)蔫磨,到一定程度就會nan淘讥,這個nan我就無法理解了,按道理來說堤如,從loss來看我們定義的來自以log蒲列,如果為無窮那么應(yīng)該是log(0)了窒朋,但是我們的discriminator出來的函數(shù)是sigmoid啊,sigmoid不可能為0蝗岖,只看是0-1且不包括閉區(qū)間侥猩。這個問題比較玄學(xué)。

既然nan的話抵赢,我也不深究是因?yàn)樯读耸媚傊@個重點(diǎn)在于loss,因?yàn)楹竺鍳AN的變種基本上都是在loss的訓(xùn)練形式上瓣俯。

GAN 生成mnist

我們現(xiàn)在玩一下mnist把。

交流

我見了一個GAN群兵怯,加我微信讓我拉進(jìn)來彩匕。jintianiloveu, 順便下載一個我做的app吧,內(nèi)側(cè)中媒区,專門用來看美女圖片的驼仪,你懂得。袜漩。傳送門

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绪爸,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子宙攻,更是在濱河造成了極大的恐慌奠货,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡凭舶,警方通過查閱死者的電腦和手機(jī)文兑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來情竹,“玉大人,你說我怎么就攤上這事∩急啵” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵咆霜,是天一觀的道長邓馒。 經(jīng)常有香客問我,道長蛾坯,這世上最難降的妖魔是什么绒净? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮偿衰,結(jié)果婚禮上挂疆,老公的妹妹穿的比我還像新娘改览。我一直安慰自己,他們只是感情好缤言,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布宝当。 她就那樣靜靜地躺著,像睡著了一般胆萧。 火紅的嫁衣襯著肌膚如雪庆揩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天跌穗,我揣著相機(jī)與錄音订晌,去河邊找鬼。 笑死蚌吸,一個胖子當(dāng)著我的面吹牛锈拨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播羹唠,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼奕枢,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了佩微?” 一聲冷哼從身側(cè)響起缝彬,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎哺眯,沒想到半個月后谷浅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡奶卓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年壳贪,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寝杖。...
    茶點(diǎn)故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡违施,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瑟幕,到底是詐尸還是另有隱情磕蒲,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布只盹,位于F島的核電站辣往,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏殖卑。R本人自食惡果不足惜站削,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望孵稽。 院中可真熱鬧许起,春花似錦十偶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至猛频,卻和暖如春狮崩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鹿寻。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工睦柴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人毡熏。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓坦敌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親招刹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容