<label id="jgr5k"></label>
    <legend id="jgr5k"><track id="jgr5k"></track></legend>

    <sub id="jgr5k"></sub>
  1. <u id="jgr5k"></u>
      久草国产视频,91资源总站,在线免费看AV,丁香婷婷社区,久久精品99久久久久久久久,色天使av,无码探花,香蕉av在线
      您正在使用IE低版瀏覽器,為了您的雷峰網(wǎng)賬號安全和更好的產(chǎn)品體驗,強烈建議使用更快更安全的瀏覽器
      此為臨時鏈接,僅用于文章預(yù)覽,將在時失效
      人工智能開發(fā)者 正文
      發(fā)私信給AI研習(xí)社
      發(fā)送

      0

      只需 130 行代碼,用 GAN 生成二維樣本的小例子

      本文作者: AI研習(xí)社 2017-06-30 14:42
      導(dǎo)語:GAN 真的很復(fù)雜?

      雷鋒網(wǎng)按:此前雷鋒網(wǎng)曾編譯了一篇英文教程,詳細介紹了如何基于 PyTorch 平臺用 50 行代碼實現(xiàn) GAN(生成對抗網(wǎng)絡(luò)),詳情參見:《GAN 很復(fù)雜?如何用不到 50 行代碼訓(xùn)練 GAN》。近期,針對文中介紹的“50 行代碼 GAN 模型”,有開發(fā)者指出了局限性,并基于此模型給出了改進版本,也就是本文將要介紹的“130 行代碼實現(xiàn) GAN 二維樣本”。本文原載于知乎專欄,作者達聞西,雷鋒網(wǎng)經(jīng)授權(quán)發(fā)布。

      50行GAN代碼的問題

      Dev Nag 寫的 50 行代碼的 GAN,大概是網(wǎng)上流傳最廣的,關(guān)于GAN最簡單的小例子。這是一份用一維均勻樣本作為特征空間(latent space)樣本,經(jīng)過生成網(wǎng)絡(luò)變換后,生成高斯分布樣本的代碼。結(jié)構(gòu)非常清晰,卻有一個奇怪的問題,就是判別器(Discriminator)的輸入不是2維樣本,而是把整個mini-batch整體作為一個維度是batch size(代碼中batch size等于cardinality)那么大的樣本。也就是說判別網(wǎng)絡(luò)要判別的不是一個一維的目標分布,而是batch size那么大維度的分布:

      ...

      d_input_size = 100   # Minibatch size - cardinality of distributions

      ...

      class Discriminator(nn.Module):

          def __init__(self, input_size, hidden_size, output_size):

              super(Discriminator, self).__init__()

              self.map1 = nn.Linear(input_size, hidden_size)

              self.map2 = nn.Linear(hidden_size, hidden_size)

              self.map3 = nn.Linear(hidden_size, output_size)


          def forward(self, x):

              x = F.elu(self.map1(x))

              x = F.elu(self.map2(x))

              return F.sigmoid(self.map3(x))

      ...

      D = Discriminator(input_size=d_input_func(d_input_size), hidden_size=d_hidden_size, output_size=d_output_size)

      ...

      for epoch in range(num_epochs):

          for d_index in range(d_steps):

              # 1. Train D on real+fake

              D.zero_grad()


              #  1A: Train D on real

              d_real_data = Variable(d_sampler(d_input_size))

              d_real_decision = D(preprocess(d_real_data))

              d_real_error = criterion(d_real_decision, Variable(torch.ones(1)))  # ones = true

              d_real_error.backward()  # compute/store gradients, but don't change params


              #  1B: Train D on fake

              d_gen_input = Variable(gi_sampler(minibatch_size, g_input_size))

              d_fake_data = G(d_gen_input).detach()  # detach to avoid training G on these labels

              d_fake_decision = D(preprocess(d_fake_data.t()))

              d_fake_error = criterion(d_fake_decision, Variable(torch.zeros(1)))  # zeros = fake

              d_fake_error.backward()

              d_optimizer.step()  # Only optimizes D's parameters; changes based on stored gradients from backward()


          for g_index in range(g_steps):

              # 2. Train G on D's response (but DO NOT train D on these labels)

              G.zero_grad()


              gen_input = Variable(gi_sampler(minibatch_size, g_input_size))

              g_fake_data = G(gen_input)

              dg_fake_decision = D(preprocess(g_fake_data.t()))

              g_error = criterion(dg_fake_decision, Variable(torch.ones(1)))  # we want to fool, so pretend it's all genuine


              g_error.backward()

              g_optimizer.step()  # Only optimizes G's parameters


      ...

      不知作者是疏忽了還是有意為之,總之這么做的結(jié)果就是如此簡單的例子收斂都好。可能作者自己也察覺了收斂問題,就想把方差信息也放進來,于是又寫了個預(yù)處理函數(shù)(decorate_with_diffs)計算出每個樣本距離一批樣本中心的距離平方,作為給判別網(wǎng)絡(luò)的額外輸入,其實這樣還增加了輸入維度。結(jié)果當然是加不加這個方差信息都能勉強收斂,但是都不穩(wěn)定。甚至作者自己貼出來的生成樣本分布(下圖)都不令人滿意:

      只需 130 行代碼,用 GAN 生成二維樣本的小例子

      如果直接把這份代碼改成二維的,就會發(fā)現(xiàn)除了簡單的對稱分布以外,其他分布基本都無法生成。

      理論上講神經(jīng)網(wǎng)絡(luò)作為一種通用的近似函數(shù),只要capacity夠,學(xué)習(xí)多少維分布都不成問題,但是這樣寫法顯然極大增加了收斂難度。更自然的做法應(yīng)該是:判別網(wǎng)絡(luò)只接受單個二維樣本,通過batch size或是多步迭代學(xué)習(xí)分布信息。

      另:這份代碼其實有130行。

      從自定義的二維分布采樣

      不管怎樣Dev Nag的代碼還是提供了一個用于理解和試驗GAN的很好的框架,做一些修改就可以得到一份更適合直觀演示,且更容易收斂的代碼,也就是本文的例子。

      從可視化的角度二維顯然比一維更直觀,所以我們采用二維樣本。第一步,當然是要設(shè)定一個目標分布,作為二維的例子,分布的定義方式應(yīng)該盡量自由,這個例子中我們的思路是通過灰度圖像定義的概率密度,進而來產(chǎn)生樣本,比如下面這樣:

      只需 130 行代碼,用 GAN 生成二維樣本的小例子

      只需 130 行代碼,用 GAN 生成二維樣本的小例子

      只需 130 行代碼,用 GAN 生成二維樣本的小例子

      二維情況下,這種采樣的一個實現(xiàn)方法是:求一個維度上的邊緣(marginal)概率+另一維度上近似的條件概率。比如把圖像中白色像素的值作為概率密度的相對大小,然后沿著x求和,然后在y軸上求出marginal probability density,接著再根據(jù)y的位置,近似得到對應(yīng)x關(guān)于y的條件概率。采樣的時候先采y的值,再采x的值就能近似得到符合圖像描述的分布的樣本。具體細節(jié)就不展開講解了,看代碼:

      from functools import partial

      import numpy

      from skimage import transform


      EPS = 1e-6

      RESOLUTION = 0.001

      num_grids = int(1/RESOLUTION+0.5)


      def generate_lut(img):

          """

          linear approximation of CDF & marginal

          :param density_img:

          :return: lut_y, lut_x

          """

          density_img = transform.resize(img, (num_grids, num_grids))

          x_accumlation = numpy.sum(density_img, axis=1)

          sum_xy = numpy.sum(x_accumlation)

          y_cdf_of_accumulated_x = [[0., 0.]]

          accumulated = 0

          for ir, i in enumerate(range(num_grids-1, -1, -1)):

              accumulated += x_accumlation[i]

              if accumulated == 0:

                  y_cdf_of_accumulated_x[0][0] = float(ir+1)/float(num_grids)

              elif EPS < accumulated < sum_xy - EPS:

                  y_cdf_of_accumulated_x.append([float(ir+1)/float(num_grids), accumulated/sum_xy])

              else:

                  break

          y_cdf_of_accumulated_x.append([float(ir+1)/float(num_grids), 1.])

          y_cdf_of_accumulated_x = numpy.array(y_cdf_of_accumulated_x)


          x_cdfs = []

          for j in range(num_grids):

              x_freq = density_img[num_grids-j-1]

              sum_x = numpy.sum(x_freq)

              x_cdf = [[0., 0.]]

              accumulated = 0

              for i in range(num_grids):

                  accumulated += x_freq[i]

                  if accumulated == 0:

                      x_cdf[0][0] = float(i+1) / float(num_grids)

                  elif EPS < accumulated < sum_xy - EPS:

                      x_cdf.append([float(i+1)/float(num_grids), accumulated/sum_x])

                  else:

                      break

              x_cdf.append([float(i+1)/float(num_grids), 1.])

              if accumulated > EPS:

                  x_cdf = numpy.array(x_cdf)

                  x_cdfs.append(x_cdf)

              else:

                  x_cdfs.append(None)


          y_lut = partial(numpy.interp, xp=y_cdf_of_accumulated_x[:, 1], fp=y_cdf_of_accumulated_x[:, 0])

          x_luts = [partial(numpy.interp, xp=x_cdfs[i][:, 1], fp=x_cdfs[i][:, 0]) if x_cdfs[i] is not None else None for i in range(num_grids)]


          return y_lut, x_luts


      def sample_2d(lut, N):

          y_lut, x_luts = lut

          u_rv = numpy.random.random((N, 2))

          samples = numpy.zeros(u_rv.shape)

          for i, (x, y) in enumerate(u_rv):

              ys = y_lut(y)

              x_bin = int(ys/RESOLUTION)

              xs = x_luts[x_bin](x)

              samples[i][0] = xs

              samples[i][1] = ys


          return samples


      if __name__ == '__main__':

          from skimage import io

          density_img = io.imread('batman.jpg', True)

          lut_2d = generate_lut(density_img)

          samples = sample_2d(lut_2d, 10000)


          from matplotlib import pyplot

          fig, (ax0, ax1) = pyplot.subplots(ncols=2, figsize=(9, 4))

          fig.canvas.set_window_title('Test 2D Sampling')

          ax0.imshow(density_img, cmap='gray')

          ax0.xaxis.set_major_locator(pyplot.NullLocator())

          ax0.yaxis.set_major_locator(pyplot.NullLocator())


          ax1.axis('equal')

          ax1.axis([0, 1, 0, 1])

          ax1.plot(samples[:, 0], samples[:, 1], 'k,')

          pyplot.show()

      二維GAN的小例子

      雖然網(wǎng)上到處都有,這里還是貼一下GAN的公式:

      只需 130 行代碼,用 GAN 生成二維樣本的小例子

      就是一個你追我趕的零和博弈,這在Dev Nag的代碼里體現(xiàn)得很清晰:判別網(wǎng)絡(luò)訓(xùn)一撥,然后生成網(wǎng)絡(luò)訓(xùn)一撥,不斷往復(fù)。按照上節(jié)所述,本文例子在Dev Nag代碼的基礎(chǔ)上,把判別網(wǎng)絡(luò)每次接受一個batch作為輸入的方式變成了:每次接受一個二維樣本,通過每個batch的多個樣本計算loss。GAN部分的訓(xùn)練代碼如下:

      DIMENSION = 2


      ...


      generator = SimpleMLP(input_size=z_dim, hidden_size=args.g_hidden_size, output_size=DIMENSION)

      discriminator = SimpleMLP(input_size=DIMENSION, hidden_size=args.d_hidden_size, output_size=1)


      ...


      for train_iter in range(args.iterations):

          for d_index in range(args.d_steps):

              # 1. Train D on real+fake

              discriminator.zero_grad()


              #  1A: Train D on real

              real_samples = sample_2d(lut_2d, bs)

              d_real_data = Variable(torch.Tensor(real_samples))

              d_real_decision = discriminator(d_real_data)

              labels = Variable(torch.ones(bs))

              d_real_loss = criterion(d_real_decision, labels)  # ones = true


              #  1B: Train D on fake

              latent_samples = torch.randn(bs, z_dim)

              d_gen_input = Variable(latent_samples)

              d_fake_data = generator(d_gen_input).detach()  # detach to avoid training G on these labels

              d_fake_decision = discriminator(d_fake_data)

              labels = Variable(torch.zeros(bs))

              d_fake_loss = criterion(d_fake_decision, labels)  # zeros = fake


              d_loss = d_real_loss + d_fake_loss

              d_loss.backward()


              d_optimizer.step()     # Only optimizes D's parameters; changes based on stored gradients from backward()


          for g_index in range(args.g_steps):

              # 2. Train G on D's response (but DO NOT train D on these labels)

              generator.zero_grad()


              latent_samples = torch.randn(bs, z_dim)

              g_gen_input = Variable(latent_samples)

              g_fake_data = generator(g_gen_input)

              g_fake_decision = discriminator(g_fake_data)

              labels = Variable(torch.ones(bs))

              g_loss = criterion(g_fake_decision, labels)  # we want to fool, so pretend it's all genuine


              g_loss.backward()

              g_optimizer.step()  # Only optimizes G's parameters


          ...


      ...

      和Dev Nag的版本比起來除了上面提到的判別網(wǎng)絡(luò),和樣本維度的修改,還加了可視化方便直觀演示和理解,比如用一個二維高斯分布產(chǎn)生一個折線形狀的分布,執(zhí)行:

      python gan_demo.py inputs/zig.jpg

      訓(xùn)練過程的可視化如下:

      只需 130 行代碼,用 GAN 生成二維樣本的小例子

      更多可視化例子可以參考如下鏈接:

      http://t.cn/Ro8aNJz

      Conditional GAN

      對于一些復(fù)雜的分布,原始的GAN就會很吃力,比如用一個二維高斯分布產(chǎn)生兩坨圓形的分布:

      只需 130 行代碼,用 GAN 生成二維樣本的小例子

      因為latent space的分布就是一坨二維的樣本,所以即使模型有很強的非線性,也難以把這個分布“切開”并變換成兩個很好的圓形分布。因此在上面的動圖里能看到生成的兩坨樣本中間總是有一些殘存的樣本,像是兩個天體在交換物質(zhì)。要改進這種情況,比較直接的想法是增加模型復(fù)雜度,或是提高latent space維度。也許模型可以學(xué)習(xí)到用其中部分維度產(chǎn)生一個圓形,用另一部分維度產(chǎn)生另一個圓形。不過我自己試了下,效果都不好。

      其實這個例子人眼一看就知道是兩個分布在一個圖里,假設(shè)我們已經(jīng)知道這個信息,那么生成依據(jù)的就是個條件概率。把這個條件加到GAN里,就是Conditional GAN,公式如下:

      只需 130 行代碼,用 GAN 生成二維樣本的小例子

      示意圖如下:

      只需 130 行代碼,用 GAN 生成二維樣本的小例子

      條件信息變相降低了生成樣本的難度,所以生成的樣本效果好很多。

      在網(wǎng)絡(luò)中加入條件的方式?jīng)]有固定的原則,這里我們采用的是可能最常見的方法:用one-hot方式將條件編碼成一個向量,然后和原始的輸入拼一下。注意對于判別網(wǎng)絡(luò)和生成網(wǎng)絡(luò)都要這么做,所以上面公式和C-GAN原文簡化過度的公式比起來多了兩個y,避免造成迷惑。

      C-GAN的代碼實現(xiàn)就是GAN的版本基礎(chǔ)上,利用pytorch的torch.cat()對條件和輸入進行拼接。其中條件的輸入就是多張圖片,每張定義一部分分布的PDF。比如對于上面兩坨分布的例子,就拆成兩張圖像來定義PDF:

      只需 130 行代碼,用 GAN 生成二維樣本的小例子

      具體實現(xiàn)就不貼這里了,參考本文的Github頁面:

      http://t.cn/Ro8Svq4

      加入條件信息后,兩坨分布的生成就輕松搞定了,執(zhí)行:

      python cgan_demo.py inputs/binary

      得到下面的訓(xùn)練過程可視化:

      只需 130 行代碼,用 GAN 生成二維樣本的小例子

      對于一些更復(fù)雜的分布也不在話下,比如:

      只需 130 行代碼,用 GAN 生成二維樣本的小例子

      這兩個圖案對應(yīng)的原始GAN和C-GAN的訓(xùn)練可視化對比可以在這里看到。

      應(yīng)用樣例

      其實現(xiàn)在能見到的基于 GAN 的有意思應(yīng)用基本都是 Conditional GAN,下篇打算介紹基于 C-GAN 的一個實(dan)用(teng)例子:

      提高駕駛技術(shù):用GAN去除(愛情)動作片中的馬賽克和衣服

      本文完整代碼

      http://t.cn/Ro8Svq4

      雷峰網(wǎng)版權(quán)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知

      只需 130 行代碼,用 GAN 生成二維樣本的小例子

      分享:
      相關(guān)文章

      編輯

      聚焦數(shù)據(jù)科學(xué),連接 AI 開發(fā)者。更多精彩內(nèi)容,請訪問:yanxishe.com
      當月熱門文章
      最新文章
      請?zhí)顚懮暾埲速Y料
      姓名
      電話
      郵箱
      微信號
      作品鏈接
      個人簡介
      為了您的賬戶安全,請驗證郵箱
      您的郵箱還未驗證,完成可獲20積分喲!
      請驗證您的郵箱
      立即驗證
      完善賬號信息
      您的賬號已經(jīng)綁定,現(xiàn)在您可以設(shè)置密碼以方便用郵箱登錄
      立即設(shè)置 以后再說
      主站蜘蛛池模板: 国产精品美女黄色av| 禹州市| 一亚洲一区二区中文字幕| 久久夜夜免费视频| V一区无码内射国产| 天堂8在线天堂资源bt| 武定县| 亚洲国产精品特色大片观看完整版| 国产亚洲精品??码| 国产AV国片精品有毛| 九九热在线免费播放视频| 国产乱码精品一区二三区| 欧美精品videossex少妇| 人妻少妇综合一区二区| 国产成a人亚洲精v品无码性色| 91九色TS另类国产人妖| 亚洲成人精品无码| 亚洲AV日韩AV激情亚洲| 国产成人精品久久一区二区三区| 免费看无码自慰一区二区| 国产精品亚洲二区三区三州| 亚洲 自拍 另类 欧美 综合| 中文无码毛片又爽又刺激| 中文字幕无码不卡在线| 91超碰人人在线| 国产一区二区三区高清在线观看| 欧美黑人一区| 亚洲乱码一区二区三区视色| 国产精品久久久久影院色| 亚洲精品国产综合麻豆久久99| 青青草一区二区免费精品| 国产成人av在线影院| 最大胆裸体人体牲交| 国产免费的野战视频| 人妻有码中文字幕| 国产真实乱人偷精品人妻| 国产自国产自愉自愉免费24区 | 日本三码电影在线| 内射自拍| 亚洲熟妇色自偷自拍另类| 国产中文字幕在线精品|