使用神經網路生成抽象隨機藝術
https://www.toutiao.com/a6657911844235117059/
隨著深度神經網路作為分類或迴歸模型變得非常流行,這些模型也可以用作生成模型來建立人工資料,例如建立新影像甚至文字資料。
下面是使用抽象藝術生成演算法完成的生成的影像:
生成的RGB影像(512x512)
這個實現是在python NumPy中實現的,並解釋了影像生成的工作方式。
隨機訓練神經網路時,初始化權重矩陣“W i ,i=1,....,n l +1”,其中n l 為神經網路的隱藏層數。
在這個實現中,權重將通過繪製標準正態分佈 N(μ=0,σ2=1) 來初始化,如下面的程式碼所示:
import seaborn as sns
import warnings
warnings.filterwarnings("ignore")
import argparse
import sys
import os
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import time
### Draw a large vector of random numbers by standard normal distribution
random_numbers = np.random.normal(loc=0.0, scale=1.0, size=2000)
### Now suppose we wanted to approximate the density function of those random numbers, we suppose
### the kernel density estimate to look like the standard normal distribution
sns.set_style("whitegrid")
sns.kdeplot(random_numbers, bw=0.5)
<matplotlib.axes._subplots.AxesSubplot at 0x9a66550>
隨機藝術演算法是如何工作的
神經網路主要用作分類或迴歸模型。
假設我們有一些輸入資料X i ,想要預測結果Y i ,其中X i 是維度p的向量,Y i 是維度k的向量。
在這種情況下,我們有一個預測可能的類k的分類問題。
對於生成的藝術,取決於我們想要選擇的顏色模式(RGB、灰度、CMYK和HSL(HSV)),在輸出層中我們有3個、1個、4個或3個輸出神經元。
由於(對於float資料型別)這些 “ colour-values ”(顏色值) 的範圍是[0,1],因此每個輸出神經元的 “ weighted_input ”(加權輸入) 將被轉換為一個sigmoid啟用函式,如下所示:
x = np.arange(-10, 10, 0.1)
sigmoid = 1 / (1 + np.exp(-x))
plt.plot(x, sigmoid)
plt.xlabel("weighted_input")
plt.ylabel("color-value")
plt.show()
對於隱藏層啟用,可以選擇不同的啟用函式,但是由於我們通過sigmoid對映weighted_input並希望colour-values大約在0.25-0.75範圍之間建立。因此對於每個隱藏層,tanh啟用將如下所示。注意,這個實現在預設情況下選擇預設啟用函式。在後面我寫了一個NeuralNet類,它可以通過輸入引數列表layers_dims和activations_fnc來選擇不同的隱藏層神經元和層啟用(但對於輸出層,請確保啟用函式對映到範圍[0,1])。
x = np.arange(-10, 10, 0.1)
tanh = np.tanh(x)
plt.plot(x, tanh)
plt.xlabel("x")
plt.ylabel("tanh(x)")
plt.show()
該演算法還組合了alpha通道,alpha通道是一個8位的灰度通道,該通道記錄影像中的透明度資訊,定義為透明、不透明和半透明 。當一種顏色(源圖)與另一種顏色(背景圖)混合時,例如,當一幅影像被疊加到另一幅影像上時,源圖顏色的alpha值用於確定最終的顏色。如果alpha值不透明,源圖顏色將覆蓋目標顏色;如果是透明的,源圖顏色是不可見的,顯示背景圖顏色。如果alpha值介於兩者之間,則生成的顏色具有不同程度的前後背景混合顏色,從而建立半透明效果。
輸出層中的顏色值將通過計算輸入資料的前向傳遞來生成。因此,很容易實現一個NeuralNet類及其所需的方法,在這種情況下:
class NeuralNet:
def __init__(self, layers_dims, activations_fnc, type_="classif"):
self.type_ = type_
self.W = [None] * (len(layers_dims)-1)
self.b = [None] * (len(layers_dims)-1)
self.out = [None] * (len(layers_dims)-1)
self.layers_dims = layers_dims
self.activations_fnc = activations_fnc
for i in range(len(layers_dims)-1):
self.b[i] = np.random.randn(layers_dims[i+1]).reshape(1, layers_dims[i+1])
self.W[i] = np.random.randn(layers_dims[i], layers_dims[i+1])
def sigmoid(self, x):
return 1.0 / (1.0 + np.exp(-x))
def tanh(self, x):
return np.tanh(x)
def relu(self, x):
return np.maximum(x, 0)
def identity(self, x):
return x
def softsign(self,x):
return x / (1 + np.abs(x))
def sin(self, x):
return np.sin(x)
def cos(self, x):
return np.cos(x)
def softmax(self, x):
exp_scores = np.exp(x)
out = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)
return out
def activation(self, x, t):
t = t.lower()
if t == "sigmoid":
return self.sigmoid(x)
elif t == "tanh":
return self.tanh(x)
elif t == "relu":
return self.relu(x)
elif t == "identity":
return self.identity(x)
elif t == "softsign":
return self.softsign(x)
elif t == "sin":
return self.sin(x)
elif t == "cos":
return self.cos(x)
elif t == "softmax":
return self.softmax(x)
else:
raise Exception("Non-supported activation function {}".format(t))
def multiply(self, x, W):
m = np.dot(x, W)
return m
def add(self, m, b):
return m + b
def forward(self, x):
input_ = x
for i, activation in enumerate(self.activations_fnc) :
weighted_sum = self.multiply(x=input_, W=self.W[i])
weighted_sum = self.add(m=weighted_sum, b=self.b[i])
input_ = self.out[i] = self.activation(x=weighted_sum, t=activation)
注意,權重初始化是用np.random.randn()函式和定義類方法forward()完成的計算從上一層到下一層的正向傳播。僅實現這些類方法就足夠了。這個類不包括反向傳播和訓練神經網路分類/迴歸模型所需的任何東西,因為這裡的目的在於理解藝術生成過程。
為隨機藝術生成輸入引數
由於使用者必須定義生成的影像的大小,因此image_height和image_width是必需的。
此外,必須定義使用哪種顏色模式以及是否應該使用alpha通道。
對於輸出影像,將使用numpy.ndarray來表示影像。影像的形狀將是( img_height, img_width, 4 )。如果您熟悉影像處理或卷積神經網路,通常會看到形狀( img_height, img_width, 3 )。如果我們有一個灰度影像,影像實際上是一個2D-tensor。對於灰度影像,我們只需將初始灰度的每個值複製到RGB影像第三軸的每個維數中,即可得到RGB形狀,例如通過np.resize:
到目前為止還沒有問題。但是我們生成的影像在三維中有4個通道。這來自於alpha通道的建模。預設情況下,我們只建立這個定義的影像形狀,但如果我們不想包含影像中每個畫素的alpha-channel-random-modelling,輸出的alpha值將是1(意思是完全不透明度)。RGBA變成了RGB。
對於“CMYK”、“HSV”、“HSL”(輸出範圍均為[0,1])的顏色模式,這些值將轉換為RGB格式,因為對於影像顯示和儲存,我們假設是RGB影像,python實現如下。
def init_image(rows, cols):
img = np.zeros(shape=(rows, cols, 4))
return img
def hsv_to_rgb(h, s, v):
## hsw are between 0 and 1
## returns rgb between 0 and 1
## from: https://bgrins.github.io/TinyColor/docs/tinycolor.html
h *= 6
i = np.floor(h)
f = h-i
p = v*(1-s)
q = v*(1-f*s)
t = v*(1-(1-f)*s)
mod = int(i % 6)
r = [v, q, p, p, t, v][mod]
g = [t, v, v, q, p, p][mod]
b = [p, p, t, v, v, q][mod]
return r,g,b
def hsl_to_rgb(h, s, l):
## hsl are between 0 and 1
## returns rgb between 0 and 1
def hue_to_rgb(p, q, t):
if t < 0:
t += 1
if t > 1:
t -= 1
if t < 1/6:
return p+(q-p)*6*t
if t < 1/2:
return q
if t < 2/3:
return p+(q-p)*(2/3-t)*6
if s==0:
r = g = b = l #achromatic
else:
if l < 0.5:
q = l*(1+s)
else:
q = l+s-l*s
p = 2*l-q
r = hue_to_rgb(p, q, h + 1/3)
g = hue_to_rgb(p, q, h)
b = hue_to_rgb(p, q, h - 1/3)
return r,g,b
神經網路架構
網路引數和輸入
對於神經網路,我們需要定義輸入維度、層數和啟用函式。
作為輸入,我們有一個5維向量。假設我們有一個大小為(256,256)的影像,把它看作一個二維矩陣。該演算法對每個畫素p_{i,j}計算r,g,b,a的值。
因此,在為生成的影像中的每個畫素生成r、g、b、a值作為輸入時(計算2-nested迴圈)我們取:
其中“factor=min(img height ,img width )”從而得到“input i,j =(x,y,r,z 1 ,z 2 )”。
將巢狀for迴圈中的x,y,r的值進行對映,從而建立結果影像中輸入資料的相互依賴和相關性:
注意,通過巢狀迴圈,x和y將是相互依賴的,如果生成的影像是正方形( img_height=img_width ),則輸入資料元件x和y始終小於1。
現在為生成藝術做layers和activation_fnc列表做準備工作。
注意,這也可以寫成硬編碼,而不是通過prep_nnet_arch函式定義:
def prep_nnet_arch(n_depth, n_size, activation, colormode, alpha):
layers = [5] #x, y, r, z1, z2
for i in range(n_depth):
layers.append(n_size)
colormode = colormode.lower()
### Output layer. Append number of output neurons depending on which colormode is selected
if colormode in ["rgb", "hsv", "hsl"] : #RGB
if not alpha:
layers.append(3)
else:
layers.append(4)
elif colormode == "cmyk":
if not alpha:
layers.append(4)
else:
layers.append(5)
elif colormode == "bw":
if not alpha:
layers.append(1)
else:
layers.append(2)
else:
print("Inserted colormode '{}' is not part ob supported ones: [rgb, bw, cmyk, hsv, hsl]".format(colormode))
raise Exception("Non-supported colormode {}".format(colormode))
possibles = ["sigmoid", "tanh", "relu", "identity", "softsign", "sin", "cos", "softmax"]
if not activation.lower() in possibles:
print('defined activation {} not supported in {}'.format(activation, str(possibles)))
return None
activations_fnc = [activation] * (len(layers)-2)
activations_fnc.append("sigmoid")
return layers, activations_fnc
如果執行以下程式碼 :
n_depth = 4
n_size = 10
activation = "tanh"
colormode = "rgb"
alpha = True
layers, activations_fnc = prep_nnet_arch(n_depth, n_size, activation, colormode, alpha)
print("layers: {}".format(str(layers)))
print("activations: {}".format(str(activations_fnc)))
將生成以下神經網路:
用R,G,B,A的值填充影像
def get_color_at(nnet, x, y, r, z1, z2, colormode, alpha):
input_ = np.array([x, y, r, z1, z2], dtype=np.float32).reshape(1, 5)
nnet.forward(input_)
colormode = colormode.lower()
if colormode == "rgb": ## Output via sigmoid activation mapped into range [0,1]
r = nnet.out[len(nnet.out)-1][0][0]
g = nnet.out[len(nnet.out)-1][0][1]
b = nnet.out[len(nnet.out)-1][0][2]
a_index = 3
elif colormode == "bw":
r=g=b = nnet.out[len(nnet.out)-1][0][0]
a_index = 1
elif colormode == "cmyk":
c = nnet.out[len(nnet.out)-1][0][0]
m = nnet.out[len(nnet.out)-1][0][1]
y = nnet.out[len(nnet.out)-1][0][2]
k = nnet.out[len(nnet.out)-1][0][3]
r = (1-c)*k
g = (1-m)*k
b = (1-y)*k
a_index = 4
elif colormode == "hsv":
h = nnet.out[len(nnet.out)-1][0][0]
s = nnet.out[len(nnet.out)-1][0][1]
v = nnet.out[len(nnet.out)-1][0][2]
r, g, b = hsv_to_rgb(h, s, v)
a_index = 3
elif colormode == "hsl":
h = nnet.out[len(nnet.out)-1][0][0]
s = nnet.out[len(nnet.out)-1][0][1]
l = nnet.out[len(nnet.out)-1][0][2]
r, g, b = hsl_to_rgb(h, s, l)
a_index = 3
else:
print("Inserted colormode '{}' is not part ob supported ones: [rgb, bw, cmyk, hsv, hsl]".format(colormode))
raise Exception("Non-supported colormode {}".format(colormode))
if alpha:
# Since non blackmode [rgb, cmyk, hsv, hsl] values are mapped onto [0,1] the alpha channel is also between [0,1].
#0=transparency, 1=opaque wrt. to overlaying
a = 1-abs(2*nnet.out[len(nnet.out)-1][0][a_index]-1)
a = 0.25 + 0.75*a
else:
a = 1.0
return r, g, b, a
生成影像函式
函式的要點:
1、初始化輸出影像
2、初始化網路引數(層和啟用)
3、從影像中遍歷行和列以填充r、g、b、a的值
def generate_image(img_height, img_width, n_depth, n_size, activation, colormode, alpha, z1, z2,
fname="netart.png", nnet_dict=None, save=False, show=False):
factor = min(img_height, img_width)
if nnet_dict is None:
layers, activations_fnc = prep_nnet_arch(n_depth, n_size, activation, colormode, alpha)
else:
try:
layers = nnet_dict["layers"]
activations_fnc = nnet_dict["activations_fnc"]
assert len(activations_fnc) == len(layers)-1
assert layers[0] == 5
assert activations_fnc[-1].lower() in ["sigmoid", "softmax"]
except Exception as e:
print(e)
nnet = NeuralNet(layers, activations_fnc)
img = init_image(img_height, img_width)
for i in range(img_height):
for j in range(img_width):
x = i/factor - 0.5
y = j/factor - 0.5
r_ = np.sqrt(x*x + y*y)
#Get RGBA values
r, g, b, a = get_color_at(nnet, x=x, y=y, r=r_,
z1=z1, z2=z2, colormode=colormode, alpha=alpha)
#Populate the image
img[i, j, 0] = r
img[i, j, 1] = g
img[i, j, 2] = b
img[i, j, 3] = a
if not show:
matplotlib.use("Agg")
plt.figure()
fig = plt.imshow(img, interpolation="bilinear", aspect="auto")
plt.axis("off")
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)
if show:
plt.show()
if save:
plt.imsave("{}".format(fname), img, format="png")
return img
使用隨機設定執行演算法:
## This is fix
img_height = img_width = 256
activation = "tanh"
def randomize_configs():
n_size = int(np.random.randint(low=12, high=20, size=1))
n_depth = int(24 - n_size)
colormode = np.random.choice(a=["rgb", "bw", "cmyk", "hsl", "hsv"], size=1)[0]
alpha = bool(np.random.choice(a=[True, False], size=1))
z1 = float(np.round(np.random.uniform(low=-1.0, high=1.0, size=1), decimals=5))
z2 = float(np.round(np.random.uniform(low=-1.0, high=1.0, size=1), decimals=5))
return n_size, n_depth, colormode, alpha, z1, z2
n_images = 10
if not os.path.exists("nb_output"):
os.makedirs("nb_output")
使用隨機配置執行演算法10次,並將結果儲存在nb_output子目錄中:
for i in range(n_images):
n_size, n_depth, colormode, alpha, z1, z2 = randomize_configs()
print("Settings:")
print("n_size: {}".format(n_size))
print("n_depth: {}".format(n_depth))
print("colormode: {}".format(colormode))
print("alpha: {}".format(alpha))
print("z1: {}".format(z1))
print("z2: {}".format(z2))
print("--------")
fname = "nb_output/generated_{}_{}.png".format(colormode, i+1)
print("Generated image: {}".format(i+1))
start_time = time.time()
generate_image(img_height, img_width, n_depth, n_size, activation, colormode, alpha, z1, z2,
show=True, nnet_dict=None, fname=fname, save=True)
delta = time.time() - start_time
print("Generating image {} took {} seconds".format(i+1, delta))
設定:
n_size: 13
n_depth: 11
colormode: hsv
alpha: True
z1: -0.84136
z2: 0.97109
--------
生成影像: 1
設定:
n_size: 13
n_depth: 11
colormode: rgb
alpha: True
z1: -0.72624
z2: -0.19368
--------
生成影像: 2
設定:
n_size: 14
n_depth: 10
colormode: bw
alpha: False
z1: 0.14255
z2: -0.38622
--------
生成影像: 3
設定:
n_size: 12
n_depth: 12
colormode: rgb
alpha: True
z1: -0.39475
z2: -0.67197
--------
生成影像: 4
設定:
n_size: 12
n_depth: 12
colormode: hsl
alpha: True
z1: 0.95898
z2: -0.00935
--------
生成影像: 5
設定:
n_size: 18
n_depth: 6
colormode: bw
alpha: False
z1: 0.30633
z2: 0.09442
--------
生成影像: 6
設定:
n_size: 19
n_depth: 5
colormode: bw
alpha: True
z1: 0.91837
z2: -0.34998
--------
生成影像: 7
設定:
n_size: 15
n_depth: 9
colormode: hsl
alpha: True
z1: -0.385
z2: 0.92596
--------
生成影像: 8
設定:
n_size: 18
n_depth: 6
colormode: bw
alpha: False
z1: 0.72774
z2: -0.89946
--------
生成影像: 9
設定:
n_size: 15
n_depth: 9
colormode: cmyk
alpha: True
z1: 0.14114
z2: 0.49769
--------
生成影像: 10
生成具有定義的網路引數的影像
如上所述,可以通過層列表來定義隱藏層尺寸和隱藏層內的神經元。
確保層列表的第一個元素是5(因為有5個輸入值)。因此層[0]= 5。
在CMYK顏色模式的情況下,輸出神經元的大小應該是4。因此層[-1]= 4。
對於RGB、B&W、HSV、HSL等顏色模式,輸出神經元均為3。因此層[-1]= 3。
如果alpha通道也被使用,輸出層需要被1填充。因此層[-1] +=1。
img_height = img_width = 512
colormode = "cmyk"
alpha = False
activations_fnc = ["tanh", "softsign", "identity", "tanh", "sigmoid"]
layers = [5, 10, 8, 18, 13, 4]
if alpha:
layers[-1] += 1
nnet_dict = {"layers":layers, "activations_fnc":activations_fnc}
z1 = -0.99
z2 = 0.85
start_time = time.time()
generate_image(img_height=img_height, img_width=img_width,
n_depth=None, n_size=None, activation=None,
colormode=colormode, alpha=alpha, z1=z1, z2=z2,
nnet_dict=nnet_dict,
show=True, save=False)
delta = time.time() - start_time
print("Generating image took {} seconds".format(delta))
img_height = img_width = 512
colormode = "hsv"
alpha = True
activations_fnc = ["tanh", "softsign", "relu", "tanh", "sigmoid"]
layers = [5, 10, 20, 18, 25, 3]
if alpha:
layers[-1] += 1
nnet_dict = {"layers":layers, "activations_fnc":activations_fnc}
z1 = -0.45
z2 = 0.66
start_time = time.time()
generate_image(img_height=img_height, img_width=img_width,
n_depth=None, n_size=None, activation=None,
colormode=colormode, alpha=alpha, z1=z1, z2=z2,
nnet_dict=nnet_dict,
show=True, save=False)
delta = time.time() - start_time
print("Generating image took {} seconds".format(delta))
img_height = img_width = 512
colormode = "bw"
alpha = False
activations_fnc = ["tanh", "softsign", "softsign", "tanh", "sigmoid"]
layers = [5, 10, 30, 40, 50, 3]
if alpha:
layers[-1] += 1
nnet_dict = {"layers":layers, "activations_fnc":activations_fnc}
z1 = 0.255
z2 = 0.900
start_time = time.time()
generate_image(img_height=img_height, img_width=img_width,
n_depth=None, n_size=None, activation=None,
colormode=colormode, alpha=alpha, z1=z1, z2=z2,
nnet_dict=nnet_dict,
show=True, save=False)
delta = time.time() - start_time
print("Generating image took {} seconds".format(delta))
img_height = img_width = 512
colormode = "hsl"
alpha = False
activations_fnc = ["tanh", "sin", "cos", "tanh", "sigmoid"]
layers = [5, 20, 10, 30, 40, 3]
if alpha:
layers[-1] += 1
nnet_dict = {"layers":layers, "activations_fnc":activations_fnc}
z1 = 0.255
z2 = 0.900
start_time = time.time()
generate_image(img_height=img_height, img_width=img_width,
n_depth=None, n_size=None, activation=None,
colormode=colormode, alpha=alpha, z1=z1, z2=z2,
nnet_dict=nnet_dict,
show=True, save=False)
delta = time.time() - start_time
print("Generating image took {} seconds".format(delta))
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29829936/viewspace-2636099/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 生成型神經網路神經網路
- 隨機森林VS神經網路:哪個更好?隨機森林神經網路
- Python丨使用深度神經網路去除馬賽克,讓藝術作品重見天日Python神經網路
- 文字生成神經網路架構發展神經網路架構
- 一文詳解隨機神經網路結構搜尋 (SNAS)隨機神經網路
- 神經網路:numpy實現神經網路框架神經網路框架
- 神經網路神經網路
- 神經網路入門篇:詳解隨機初始化(Random+Initialization)神經網路隨機random
- 雙向迴圈神經網路+條件隨機場進行分詞神經網路條件隨機場分詞
- 機器學習整理(神經網路)機器學習神經網路
- LSTM神經網路神經網路
- 8、神經網路神經網路
- 聊聊從腦神經到神經網路神經網路
- 圖神經網路GNN 庫,液體神經網路LNN/LFM神經網路GNN
- 使用TensorRT部署你的神經網路(1)神經網路
- 【神經網路篇】--RNN遞迴神經網路初始與詳解神經網路RNN遞迴
- 【深度學習篇】--神經網路中的卷積神經網路深度學習神經網路卷積
- 神經網路篇——從程式碼出發理解BP神經網路神經網路
- 人工神經網路(ANN)神經網路
- 卷積神經網路卷積神經網路
- 迴圈神經網路神經網路
- 神經網路(neural networks)神經網路
- 利用神經網路為大頭照生成卡通表情包(Memoji)神經網路
- 【機器學習】搭建神經網路筆記機器學習神經網路筆記
- 機器學習:神經網路構建(上)機器學習神經網路
- 機器學習:神經網路構建(下)機器學習神經網路
- 從規則到神經網路:機器翻譯技術的演化之路神經網路
- 使用tf.estimator.Estimator訓練神經網路神經網路
- 使用NumPy演示實現神經網路過程神經網路
- 使用PyTorch演示實現神經網路過程PyTorch神經網路
- MATLAB神經網路工具箱使用介紹Matlab神經網路
- 神經網路中使用的啟用函式神經網路函式
- 使用Math類生成隨機數隨機
- Tensorflow系列專題(四):神經網路篇之前饋神經網路綜述神經網路
- 卷積神經網路學習筆記——Siamese networks(孿生神經網路)卷積神經網路筆記
- 再用RNN神經網路架構設計生成式語言模型RNN神經網路架構模型
- 前沿高階技術之遞迴神經網路(RNN)遞迴神經網路RNN
- 機器學習之多類別神經網路:Softmax機器學習神經網路