用生成模型學習高維自然信號(比如圖像、視頻和音頻)長期以來一直是機器學習的重要發展方向之一。來自 Uber AI Lab 的 Yunus Saatchi 等人今年五月提出了 Bayesian GAN——利用一個簡單的貝葉斯公式進行端到端無監督/半監督 GAN 學習。該研究的論文已被列入 NIPS 2017 大會 Spotlight。最近,這篇論文的另一作者 Andrew Gordon Wilson 在 GitHub 上發佈了 Bayesian GAN 的 TensorFlow 實現。
項目鏈接:https://github.com/andrewgordonwilson/bayesgan/
論文:Bayesian GAN
論文鏈接:https://arxiv.org/abs/1705.09558
摘要:生成對抗網絡(GAN)可以隱性地學習難以用顯性似然(explicit likelihood)建模的圖像、音頻和數據的豐富分佈。我們展示了一種實際的貝葉斯公式,用 GAN 進行無監督和半監督學習。在該框架下,我們使用隨機梯度哈密爾頓蒙特卡羅(Hamiltonian Monte Carlo)來邊緣化生成器和判別器的權重。得到的方法很直接,且可在沒有標準干預(如特徵匹配或小批量判別)的情況下達到不錯的性能。通過探索生成器參數具有表達性的後驗,貝葉斯 GAN 避免了模式崩潰(mode-collapse),輸出可解釋的多種候選樣本,在 SVHN、CelebA 和 CIFAR-10 等多個基準數據集上取得了頂尖的半監督學習量化結果,優於 DCGAN、Wasserstein GAN 和 DCGAN。
介紹
在貝葉斯 GAN 中,我們提出了生成器和判別器權重的條件後驗,通過隨機梯度哈密爾頓蒙特卡羅邊緣化這些後驗。貝葉斯 GAN 的主要特性有:(1)在半監督學習問題上的準確預測;(2)對優秀性能的最小干預;(3)響應對抗反饋的推斷的概率公式;(4)避免模式崩潰;(5)展示多個互補的生成和判別模型,形成一個概率集成(probabilistic ensemble)。
我們介紹了一個生成器參數的多模態後驗。這些參數的每個設置對應數據的不同生成假設。這裏我們將展示兩種權重向量設置下生成的樣本,不同的權重向量設置對應不同的寫作風格。貝葉斯 GAN 保留該參數分佈。相反,標準 GAN 用點估計(類似最大似然解決方案)來展示整個分佈,降低了數據的可解釋性。
環境需求
該代碼有以下依賴項(版本號很關鍵)
python 2.7
tensorflow==1.0.0
在 Linux 上安裝 TensorfFow 1.0.0,請按照 https://www.tensorflow.org/versions/r1.0/install/說明進行操作。
scikit-learn==0.17.1
你可以使用下列命令安裝 scikit-learn 0.17.1:
pip install scikit-learn==0.17.1
或者,使用提供的 environment.yml 文件創建 conda 環境,並進行設置:
conda env create -f environment.yml -n bgan
然後,使用下列命令加載環境:
source activate bgan
訓練選項
bayesian_gan_hmc.py 具備以下訓練選項。
--out_dir:文件夾路徑,用於存儲輸出
--n_save: 每 n_save 次迭代存儲的樣本和權重;默認值 100
--z_dim: 生成器 z 向量的維度;默認值 100
--data_path:數據路徑;具體討論詳見 https://github.com/andrewgordonwilson/bayesgan/#data-preparation;該參數是必需的
--dataset:可以是 mnist、cifar、svhn 或 celeb;默認 mnist
--gen_observed: 生成器「觀察到」的數據;影響噪聲變量和先驗的縮放;默認值 1000
--batch_size:訓練的批量大小;默認值 64
--prior_std:權重先驗分佈的 std;默認值 1
--numz:和論文中的 J 一樣; z 的樣本數,實現整合;默認值 1
--num_mcmc: 和論文中的 M 一樣;每個 z 的 MCMC NN 權重樣本數;默認值 1
--lr: Adam 優化器使用的學習率;默認值 0.0002
--optimizer:使用的優化方法:adam (tf.train.AdamOptimizer) 或 sgd (tf.train.MomentumOptimizer);默認 adam
--semi_supervised:進行半監督學習
--N:半監督學習所需標註樣本數量
--train_iter:訓練迭代次數;默認值 50000
--save_samples:保存訓練過程中生成的樣本
--save_weights:訓練過程中,保存權重
--random_seed:隨機種子;如果使用 GPU,那麼注意設置該種子不會引起 100% 的可復現結果
你還可以用--wasserstein 運行 WGAN,或用--ml_ensemble
使用
安裝
1. 安裝所需依賴項
2. 複製該 repository
合成數據
你可以使用 bgan_synth 腳本運行論文中的合成實驗。例如,以下命令用於訓練貝葉斯 GAN(D=100,d=10),進行 5000 次迭代,並把結果保存在
./bgan_synth.py --x_dim 100--z_dim 10--numz 10--out <results_path>
運行以下命令使用相同的數據運行 ML GAN:
./bgan_synth.py --x_dim 100--z_dim 10--numz 1--out <results_path>
bgan_synth 的參數有 --save_weights、--out_dir、--z_dim、--numz、--wasserstein、--train_iter 和 --x_dim。x_dim 控制觀測數據(論文中的 x)的維度。通過這個鏈接查看其它參數的說明:https://github.com/andrewgordonwilson/bayesgan/#training-option。
運行了上面的兩個命令之後,你可以在
相對地,標準 GAN(numz=1,強制執行 ML 評估)的輸出結果如下:
可以清晰地看到在這個合成數據的例子中,標準 GAN 出現了模式崩潰的趨勢,而貝葉斯 GAN 完全沒有這樣的問題。
你可以查看 synth.iptnb,進一步探索合成實驗,並生成詹森-香農差異圖。
MNIST、CIFAR10、CELEBA、SVHN
bayesian_gan_hmc 腳本允許在標準和自定義數據集上訓練模型。下面,我們將介紹如何使用該腳本。
數據準備
爲了重現在 MNIST、CIFAR10、CelebA 和 SVHN 數據集上的實驗,你需要準備這些數據,並使用一個正確的——data_path。
對於 MNIST,你不需要準備數據,並可以提供任意的——data_path;
對於 CIFAR10,請從該地址(https://www.cs.toronto.edu/~kriz/cifar.html)下載和獲取數據的 Python 版本;然後使用包含 cifar-10-batchs-py 的目錄的路徑作爲——data_path;
對於 SVHN,請從該地址(http://ufldl.stanford.edu/housenumbers/)下載 train_32x32.mat 和 test_32x32.mat 文件,並使用包含這些文件的目錄的路徑作爲——data_path;
對於 CelebA,你需要安裝 OpenCV。數據下載地址:http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html。你需要創建 celebA 文件夾,該文件夾包含 Anno 和 img_align_celeba 子文件夾。其中 Anno 必須包含 list_attr_celeba.txt,img_align_celeba 必須包含.jpg 文件。你還需要通過在——data_path
(其中 是包含了 celebA 的文件夾的路徑)中運行 datasets/crop_faces.py 腳本對圖像進行剪裁。訓練模型的時候,你需要在——data_path 中使用相同的 。
無監督學習
你可以在沒有 -- semi 參數的情況下通過運行 bayesian_gan_hmc 腳本對模型進行無監督訓練。例如,使用以下命令:
./bayesian_gan_hmc.py --data_path <data_path>--dataset svhn --numz 1--num_mcmc 10--out_dir
<results_path>--train_iter 75000--save_samples --n_save 100
在 SVHN 數據集上訓練模型。該命令會使用這個方法執行 75000 次迭代,每 100 次迭代保存樣本。這裏
半監督訓練
你可以使用--semi 選項來運行 bayesian_gan_hmc,對模型進行半監督訓練。使用-N 參數設置訓練所用標註樣本的數量。例如,使用
./bayesian_gan_hmc.py --data_path <data_path>--dataset cifar --numz 1--num_mcmc 10
--out_dir <results_path>--train_iter 75000--N 4000--semi --lr 0.00005
在 CIFAR10 數據集上用 4000 個標註樣本訓練該模型。該命令使訓練經歷 75000 次迭代,輸出結果儲存在
要想在 MNIST 數據集上使用 200 個標註樣本訓練該模型,你需要使用以下命令:
./bayesian_gan_hmc.py --data_path <data_path>/--dataset mnist --numz 5--num_mcmc 5
--out_dir <results_path>--train_iter 30000-N 200--semi --lr 0.001
自定義數據
要想在自定義數據集上訓練該模型,你需要用特定的接口定義類別。假設我們想在 digits 數據集上訓練模型。該數據集包含 8x8 數字圖像。假設數據的儲存格式爲 x_tr.npy、y_tr.npy、x_te.npy 和 y_te.npy。我們假設 x_tr.npy 和 x_te.npy 的形態爲 (?, 8, 8, 1)。然後在 bgan_util.py 中定義該數據集對應的類別,如下所示:
classDigits:
def__init__(self):
self.imgs =np.load('x_tr.npy')
self.test_imgs =np.load('x_te.npy')
self.labels =np.load('y_tr.npy')
self.test_labels =np.load('y_te.npy')
self.labels =one_hot_encoded(self.labels,10)
self.test_labels =one_hot_encoded(self.test_labels,10)
self.x_dim =[8,8,1]
self.num_classes =10
@staticmethod
defget_batch(batch_size,x,y):
"""Returns a batch from the given arrays.
"""
idx =np.random.choice(range(x.shape[0]),size=(batch_size,),replace=False)
returnx[idx],y[idx]
defnext_batch(self,batch_size,class_id=None):
returnself.get_batch(batch_size,self.imgs,self.labels)
deftest_batch(self,batch_size):
returnself.get_batch(batch_size,self.test_imgs,self.test_labels)
該類別必須具備 next_batch 和 test_batch,以及 imgs、labels、test_imgs、test_labels、x_dim 和 num_classes。
現在,我們可以把 Digits 類輸入到 bayesian_gan_hmc.py:
frombgan_util importDigits
將下列行添加至處理--dataset 參數的代碼中:
ifargs.dataset =="digits":
dataset =Digits()
準備過程完成後,我們可以使用以下命令訓練模型:
./bayesian_gan_hmc.py --data_path <any_path>--dataset digits --numz 1--num_mcmc 10
--out_dir <results path>--train_iter 5000--save_samples