使用deep dream做了很多圖,從中確實能直觀地學到一些東西。
下面是自己做的視頻,使用不同通道生成了一些圖形,並對比了不同的迭代次數下生成的圖片。
https://www.bilibili.com/video/av65825597/
https://www.bilibili.com/video/av65882277/
https://www.bilibili.com/video/av65973012/
使用inception v3的通道對圖片進行梯度上升完成訓練。
圖片被壓縮,分成高低頻,恢復原尺度的過程逐漸訓練,完成大尺寸圖的deep dream訓練。
有些有意思的點總結一下:
1.一個通道不夠代表一個“類別”
這是肯定的,畢竟不是softmax輸出,只是卷積層,卷積層抽象出來的是一個特徵。每個通道可能只通過某一種特徵,比如蛇的鱗、比如狗頭、比如人的嘴,比如猩猩的臉,不同通道組合起來共同產生一個類別的特徵集合才足證一個類別。
2.一個通道不只代表一個“類別”
上圖都是高次數迭代的抽象圖,如果迭代不同的次數,會發現有些特徵在迭代次數少的時候有,高的時候被覆蓋了。說明一個通道也不止“一個”特徵(這裏的一個都是人類思維)
如下圖,低次迭代時,能看到類似孔雀羽毛或者狗頭之類的東西,總之是毛茸茸的,而遠處的圖形(比較好訓練)先成了彩色圓管。但是高次迭代後,這些毛茸茸的東西都消失了,主要集中在彩色的圓管形狀。我的認知是,一個通道有多個特徵,每個特徵的權重不同,佔的權重大的很容易凸顯,尤其高次迭代訓練後。(我說的權重可能是比重,而不是weight具體數值,但是也許對應關係差不多)
3.高低頻都代表什麼?
在梯度上升進行deep dream操作中,小型圖片是一次性操作,但是對大型圖片的deep dream涉及到圖片的縮放和高低頻分離。
如下,高低頻的分離代碼,循環是圖片縮放,循環內是高低頻分離,留下低頻,高頻統一放在數組中。
lo就是圖片縮小,hi是原圖減去lo的再放大(不然像素不對),lo的一縮一放導致圖片“失真”,hi就是原圖剪掉這些失真部分,所以(不同尺度下)hi永遠都是輪廓
(後續的操作——梯度上升迭代,也是基於這個分離,先給低頻圖做地圖上升,然後逐漸放大,並且把hi加回去,一直放大到原圖尺寸,從而保留高頻“邊緣信息”)
octaves = []
for i in range(octave_n - 1):
hw = img.shape[:2]
lo = resize(img, np.int32(np.float32(hw) / octave_scale))
hi = img - resize(lo, hw)
hi_print = hi.copy()
lo_print = lo.copy()
img = lo
octaves.append(hi)
如下三圖,分別爲原圖、高頻圖、低頻圖。可以看到,高頻圖只剩下輪廓,而低頻圖(相較原圖)則丟失了輪廓,用我的話說,叫銳度降低、邊緣淡化、圖片平面化。總之就是山的邊角輪廓已經不分明瞭(雖然你根據經驗,還是覺得山上有懸崖,還是覺得近處的山和遠處的水是分開的)
其他的,想到了再補充,有空也會傳更多通道的抽象圖片的視頻