編者按:Google Brain機器學習開發者hardmu使用TensorFlow,基于CPPN網絡生成了許多有趣的高分辨率抽象藝術圖片。一起來看看他是怎么做的吧。
鉆石恒久遠
本文嘗試使用TensorFlow探索復合模式生成網絡(Compositional pattern-producing networks)。相關代碼放在github上。乍看起來,用TensorFlow實現CPPN是高射炮打蚊子,因為用numpy就可以實現CPPN。不過,用TensorFlow方便我們以后進一步擴展。
介紹
近來,基于神經網絡的圖像生成技術通常使用嘗試一次性繪制整個圖像的生成網絡。例如,如果輸出圖像的目標分辨率是256x256,那么神經網絡的最后一層會有65536個值(黑白圖像)。由于內存和這些算法的可擴展性方面的限制,將輸出分辨率提高到現代圖像的分辨率(2880x1800)可能是不可行的。
在這篇文章中,我將描述一個非常簡單的生成高分辨率的圖像的方法。神經網絡并不一次性生成所有像素,而是根據像素的位置生成單個像素的亮度或顏色。然后,為目標輸出圖像中的每個像素查詢一次網絡,從而生成整個圖像。這種方法可以用來生成高分辨率的圖像,圖像的分辨率大小將僅僅受限于內存,同時提供了一個縮放圖像的優雅方式,并且圖像會具有一些分形特性。
網上已經有一些demo試驗了這一技術,包括karpathy基于convnetjs的繪圖demo,以及生成式神經網絡藝術和Neurogram的javascript實現。
在這篇文章中,我將介紹如何基于TensorFlow實現這個簡單的技術,以生成隨機的抽象藝術。我想使用TensorFlow來實現這個功能,是因為它可以作為基礎,在未來利用TensorFlow的機器學習能力做些更有趣的事情。這種類型的生成網絡還可以用來創建非隨機圖片,我將在以后的帖子中討論這一點。
復合模式生成網絡
我們定制的CPPN的語義
我在以前的一個帖子中介紹過CPPN的基礎情況,其中使用CPPN結合NEAT算法來演化生成式神經網絡。
本質上,CPPN只是一個函數,c=f(x, y),該函數定義了空間中每個點的圖像亮度。這使得CPPN很適合生成高分辨率的圖像,因為,給定像素的位置,你可以直接調用這個函數來獲取每個像素的顏色或亮度。
f(x, y)這個函數可以通過很多數學運算構建,也可以通過神經網絡來表示,該神經網絡包含一個連接激活門的權重集合,其中的權重在繪制圖像時保持不變。因此整個圖像可以被定義為f(w, x, y)。
我們的TensorFlow實現將與之前基于CPPN-NEAT的工作略有不同。像之前的工作一樣,f(x, y)將返回一個0到1之間的實數,以定義該點處的圖像亮度(結果將是灰度圖像)或一個三維向量,向量的每個值在(0, 1)之內,以表示彩色亮度(紅、綠、藍)。此外,與CPPN-NEAT類似,為了使圖像更有趣,我們還將每個點到原點的距離作為輸入(r = sqrt(x^2+y^2)),因此CPPN函數為f(w, x, y, r)。神經網絡的權重w將被初始化為單位高斯分布的隨機值。
與CPPN-NEAT不同,我們要在這個實現中使用的神經網絡將僅僅是一個由用戶定義的多層前饋網絡。例如,用戶可以修改TensorFlow代碼,使f(w, x, y, r)成為由雙曲線正切、relu、softplus、正弦曲線等定義的前饋神經網絡。每一層還將有一個額外的偏置輸入,出于簡明的考慮,圖中省略了這個偏置輸入。
我們還將在CPPN函數中添加一個稱為潛向量的額外輸入z,這是一個包含n個實數的向量(n通常遠小于網絡中加權連接的總數),所以我們的生成網絡定義為f(w, z, x, y, r)。修改z的值會導致我們的網絡產生不同的圖像,而通過改變z的值我們的網絡可能生成的整個圖像空間被稱為潛空間。從某種意義上說,z可以被解釋為基于n個實數對最終圖像的壓縮描述。由于網絡是一個連續的函數,如果我們稍微調整z的值,那么輸出圖像也只會稍微變化,所以我們也可以通過使用一個從z1緩慢地移動到z2的潛向量z生成一系列圖像,從而可視化潛空間中的一張圖像如何緩慢地漸變為同一潛空間中的另一張圖像。
注意,示意圖中的空白層只是在進入第一個隱藏層之前,應用縮放因子至x、y、r和z的一個預處理層。
我們本可以逐漸調整權重來獲得不同的輸出圖像,之所以需要一個額外的潛向量輸入,是因為,一個復雜的生成式網絡可能有成百上千的權重,并且在許多生成應用中,我們希望將潛向量的數量控制在一個很小的值。當我們最終在大型數據集上進行訓練時,潛向量不僅可以控制正在繪制的對象,還可以控制圖像的特定風格。使用概率論的一些工具,我們甚至可以強制z具有良好的性質,例如獨立和單位高斯。例如,z的一個子集可以表示個人性別,另一個子集可以表示由生成算法繪制的人臉的情緒。在后續的帖子中,我們會試圖訓練這類CPPN來書寫數字,也可能會繪制臉部、動物、汽車、廁所,等等。
探索神經網絡的潛空間
生成.png和.gif圖像的CPPN模型和代碼可以在github上找到。我將使用代碼作為參考,以通過IPython會話生成圖像。
在代碼倉庫中,model.py包含使用TensorFlow庫常規生成圖像的CPPN類。如果你打算嘗試修改CPPN的神經網絡架構,可以查看一下generator方法。其中有一些替代架構被注釋掉了,這些架構可供嘗試。我們將使用sampler.py文件中的Sampler類,這允許我們互動請求IPython會話內的圖像。
在IPython會話內,我們首先進入倉庫目錄并運行:
%run -i sampler.py
sampler = Sampler(z_dim = 8, scale = 10.0, net_size = 32)
Sampler將生成一個CPPN模型,該模型使用包含8個實數的潛向量,10倍放大,在每個神經網絡層包含32個激活函數。注意這些是默認值,因此我們下次也可以直接使用sampler = Sampler()。
為了生成圖像,我們需要生成一個包含8個實數的隨機潛向量z:
z1 = sampler.generate_z()
之后我們可以將z傳遞給生成函數以查看輸出圖像。img_data是一個包含圖像數據的numpy數列。
img_data = sampler.generate(z1)
sampler.show_image(img_data)
輸出
調用reinit()方法可以重置和隨機化神經網絡的權重:
sampler.reinit()
sampler.show_image(sampler.generate(z1))
輸出
注意,隨著網絡權重的改變,潛空間改變了,因此盡管我們傳入了相同的z向量,我們會看到一個不同的輸出。
我們可以通過sampler.save_png(img_data, 'output.png')保存文件。
穿越潛空間
在同一潛空間中生成另一張隨機圖像:
z2 = sampler.generate_z()
sampler.show_image(sampler.generate(z2))
輸出
上面的兩種圖像均屬于同一潛空間,同時能以矢量格式緊湊地表示。如果我們從z1一點點地移動到z2,然后在每步生成一個圖像,我們可以看到由z1定義的圖像是如何漸變為由z2定義的圖像。我創建了一個如上所述生成.gif圖像的方法。該方法有一些可供調整的設置,用于調節時間和每幀的大小。默認值將生成約5M大的.gif文件。
sampler.save_anim_gif(z1, z2, 'output.gif')
輸出
著色
重置IPython會話,將c_dim設置為3后可以生成彩色圖像。
%run -i sampler.py
sampler = Sampler(z_dim = 8, c_dim = 3, scale = 10.0, net_size = 32)
我們可以讓CPPN在每個像素的位置輸出3個值,為每個像素定義RGB值。然而,我個人覺得,對于使用隨機權重的生成式網絡而言,黑白版本更為優雅。
修改網絡架構
我們也可以修改model.py內的generate方法來修改CPPN網絡的架構。
默認架構是若干包含雙曲正切函數的神經網絡層。
H = tf.nn.tanh(U)
for i in range(3):
H = tf.nn.tanh(fully_connected(H, net_size, 'g_tanh_'+str(i)))
output = tf.sigmoid(fully_connected(H, self.c_dim, 'g_final'))
例子
我們也可以在tanh層中混入softplus層:
H = tf.nn.tanh(U)
H = tf.nn.softplus(fully_connected(H, net_size, 'g_softplus_1'))
H = tf.nn.tanh(fully_connected(H, net_size, 'g_tanh_2'))
H = tf.nn.softplus(fully_connected(H, net_size, 'g_softplus_2'))
output = tf.sigmoid(fully_connected(H, self.c_dim, 'g_final'))
例子
我們甚至可以加入正弦激活函數:
H = tf.nn.tanh(U)
H = tf.nn.softplus(fully_connected(H, net_size, 'g_softplus_1'))
H = tf.nn.tanh(fully_connected(H, net_size, 'g_tanh_2'))
H = tf.nn.softplus(fully_connected(H, net_size, 'g_softplus_2'))
output = 0.5 * tf.sin(fully_connected(H, self.c_dim, 'g_final')) + 0.5
例子
我也嘗試了絕對值函數、平方根、自己實現的高斯激活函數,和殘差結構。
CPPN相當泛化,并具備同時生成大批量圖片的能力。未來我們想讓CPPN為我們生成一些有趣的東西時,批量處理對基于GPU的神經網絡訓練非常有用。
結論
TensorFlow庫提供了執行向量運算的高效方法,可用于不需要梯度運算的任務。但是這意味著未來可以利用深度學習功能擴展各種各樣的工作。像本文中的例子一樣,我們以后可以使用這些代碼,并嘗試訓練我們的CPPN做一些有趣的事情,比如,繪制某類圖像、字體或不同風格的數字,這些都在高分辨率的條件下完成。
-
神經網絡
+關注
關注
42文章
4779瀏覽量
101165 -
圖像生成
+關注
關注
0文章
22瀏覽量
6903 -
tensorflow
+關注
關注
13文章
329瀏覽量
60629 -
cppn
+關注
關注
0文章
2瀏覽量
2252
原文標題:基于TensorFlow生成抽象紋理
文章出處:【微信號:jqr_AI,微信公眾號:論智】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
單片機內置ADC實現高分辨率采樣的方法
超高分辨率圖像實時顯示系統設計
垂直分辨率與使用高分辨率示波器測量微小信號的介紹
![垂直<b class='flag-5'>分辨率</b>與使用<b class='flag-5'>高分辨率</b>示波器測量微小信號的介紹](https://file.elecfans.com/web2/M00/49/E9/pYYBAGKhvHSATMRqAABDOaAydhg619.png)
太秀了!單片機內置ADC實現高分辨率采樣?
![太秀了!單片機內置ADC<b class='flag-5'>實現</b><b class='flag-5'>高分辨率</b>采樣?](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評論