天天看點

如何用TensorFlow生成令人驚豔的分形圖案

今天來介紹一個小項目:在tensorflow中生成分形圖案。分形本身隻是一個數學概念,與機器學習并無太大關系,但是通過分形的生成,我們可以了解怎麼在tensorflow中進行數學計算,以及如何進行基本的流程控制,是學習tensorflow的一個非常好的練手項目。

mandelbrot集合

mandelbrot集合是分形中最經典的一個例子。考慮疊代公式z_{n+1}=z_{n}^2 + c(z和c都是複數)。當z_0為0時,得到的值可以組成一個數列,依次為c, c^2+c,(c^2+c)^2+c……。當該數列發散到無窮時,對應的點就屬于mandelbrot集合。

如c=0 時,顯然數列永遠是0,并不發散,是以0不屬于mandelbrot集合。

又如c=3i 時,對應的數列為3i, -9+3i, 63-51i, 1431-6477j…. ,數字越來越龐大,是以3i就屬于mandelbrot集合。

在二維平面上,将所有不屬于mandelbrot集合的點标記為黑色,将所有屬于mandelbrot集合的點按照其發散速度賦予不同的顔色,就可以得到mandelbrot的經典圖像:

如何用TensorFlow生成令人驚豔的分形圖案

上面這張圖完全是使用tensorflow進行計算的,類似的圖大家應該在網上也見過好多了,在tensorflow中,我們定義下面的計算步驟:

xs = tf.constant(z.astype(np.complex64)) 

zs = tf.variable(xs) 

ns = tf.variable(tf.zeros_like(xs, tf.float32)) with tf.session(): 

    tf.global_variables_initializer().run() 

    zs_ = tf.where(tf.abs(zs) < r, zs**2 + xs, zs) 

    not_diverged = tf.abs(zs_) < r 

    step = tf.group( 

        zs.assign(zs_), 

        ns.assign_add(tf.cast(not_diverged, tf.float32))  

    for i in range(iter_num): step.run() 

    final_step = ns.eval() 

    final_z = zs_.eval()  

zs就對應我們之前疊代公式的z,而xs就對應疊代公式中的c。為了友善起見,隻要計算時數值的絕對值大于一個事先指定的值r,就認為其發散。每次計算使用tf.where隻對還未發散的值進行計算。結合ns和zs_就可以計算顔色,得到經典的mandelbrot圖像。

julia集合

julia集合和mandelbrot集合差不多,但這次我們固定c,轉而計算發散的z的值。即c是固定的常數(可以任取),數列變成z,z^2+c,(z^2+c)^2 +c,…..。如果該數列發散,對應的z就屬于julia集合。對此,我們隻要在原來的程式中修改兩行内容,就可以生成julia集合:

xs = tf.constant(np.full(shape=z.shape, fill_value=c, dtype=z.dtype)) 

zs = tf.variable(z)  

我們在fill_value=c處指定了julia集合中的c值,隻要使用不同的c值,就可以生成完全不同的julia集合!

預設:c = -0.835 – 0.2321i :

如何用TensorFlow生成令人驚豔的分形圖案

将c值變為c = -0.8 * 1j ,并調整顔色(調整方法參考github頁面的說明):

如何用TensorFlow生成令人驚豔的分形圖案

選用c=0.285 + 0.01i ,圖案又變得完全不同:

如何用TensorFlow生成令人驚豔的分形圖案

生成julia集合的動畫

在julia集合中,每次都對c的值進行微小的改變,并将依次生成圖檔制作為gif,就可以生成如下所示的動畫,對應的代碼為julia_gif.py:

如何用TensorFlow生成令人驚豔的分形圖案

這裡由于上傳gif有大小限制的關系,隻展示了一個小尺寸的動畫圖像。程式中提供了一個width參數,可以修改它以生成更大尺寸,品質更高的動畫圖像。

探索mandelbrot集合

(注意:下面的圖檔可能對密集恐懼症患者不太友好。。。是以慎重翻頁。。)

在前面生成的mandelbrot集合中,我們可以将圖像放大,選取某些區域進行生成,就可以得到格式各樣造型迥異的分形圖案,對應的程式為mandelbrot_area.py。

在mandelbrot集合中,有很多地方圖案比較奇特,如下圖中的9個位置。

如何用TensorFlow生成令人驚豔的分形圖案

其中編号為2的地方被稱為“elephant valley”,因為此處的圖案與大象很像,直接運作mandelbrot_area.py就可以得到該區域的圖像:

如何用TensorFlow生成令人驚豔的分形圖案

編号為3的地方被稱為“triple spiral valley”(三重螺旋),在mandelbrot_area.py修改一下坐标位置為(ratio調整的是顔色):

start_x = -0.090  # x range 

end_x = -0.086 

start_y = 0.654  # y range 

end_y = 0.657 

width = 1000 

ratio1, ratio2, ratio3 = 0.2, 0.6, 0.6  

就可以得到該處的圖案:

如何用TensorFlow生成令人驚豔的分形圖案

最後編号為1的地方被稱為“seahorse valley”(海馬山谷),對應的坐标為:

start_x = -0.750  # x range 

end_x = -0.747 

start_y = 0.099  # y range 

end_y = 0.102 

ratio1, ratio2, ratio3 = 0.1, 0.1, 0.3 

圖像如下,确實和海馬有一點神似:

如何用TensorFlow生成令人驚豔的分形圖案

生成更多的圖案

本文作者:何之源

來源:51cto

繼續閱讀