GANs是在訓(xùn)練階段最需要計算的密集型模型之一,因為它相當于同時訓(xùn)練兩個神經(jīng)網(wǎng)絡(luò)。對于我的普通電腦來說,把gan訓(xùn)練到收斂是非常困難的。 遺傳算法是根據(jù)大自然中生物體進化規(guī)律而設(shè)計提出的,是根據(jù)大自然中生物體進化規(guī)律而設(shè)計提出的。是模擬達爾文生物進化論的自然選擇和遺傳學(xué)機理的生物進化過程的計算模型,是一種通過模擬自然進化過程搜索最優(yōu)解的方法。 在本片文章中,我們嘗試使用遺傳算法來對訓(xùn)練GANs進行優(yōu)化,我們的訓(xùn)練模型是生成手寫數(shù)字。 什么是遺傳算法?遺傳算法是一種學(xué)習(xí)算法,它利用交叉兩個好的神經(jīng)網(wǎng)絡(luò)的權(quán)值的思想,從而得到一個更好的神經(jīng)網(wǎng)絡(luò)。 遺傳算法如此有效的原因是沒有直接的優(yōu)化算法,所以允許有極端變化的結(jié)果的可能性。此外,他們通常會提出非常有趣的解決方案,這些方案通常會對問題提供有價值的見解。 它們?nèi)绾喂ぷ鳎?/h2>生成一組隨機權(quán)重。 這是第一個代理的神經(jīng)網(wǎng)絡(luò)。 在代理上執(zhí)行了一組測試。 代理會根據(jù)測試獲得分數(shù)。 重復(fù)幾次以創(chuàng)建種群。選擇種群的前10%以進行交叉。 從最高的10%中選擇兩個隨機的父母,他們的權(quán)重是交叉的。 每次發(fā)生交叉時,發(fā)生突變的可能性都很?。哼@是一個隨機值,不會受到父母的影響。 這個過程會慢慢地優(yōu)化代理的性能,因為代理會慢慢地適應(yīng)環(huán)境。 優(yōu)點計算不密集:沒有線性代數(shù)計算要完成。唯一必要的機器學(xué)習(xí)計算是通過神經(jīng)網(wǎng)絡(luò)的正向傳遞。因此,與深度神經(jīng)網(wǎng)絡(luò)相比,系統(tǒng)要求非常廣泛。 適應(yīng)性強:可以改編并插入許多不同的測試和方法來操縱遺傳算法的靈活性。可以通過使代理傳播生成器網(wǎng)絡(luò)并使用鑒別器作為測試,在遺傳算法內(nèi)創(chuàng)建GAN。這是一個至關(guān)重要的好處,這使我相信將來遺傳算法的使用將更加廣泛。 可解釋的:對于普通的神經(jīng)網(wǎng)絡(luò),該算法的學(xué)習(xí)模式是不可解釋的。對于遺傳算法,很容易理解為什么會發(fā)生某些事情:例如,當給遺傳算法提供Tic-Tac-Toe環(huán)境時,某些可識別的策略就會慢慢發(fā)展。這是一個很大的好處,因為使用機器學(xué)習(xí)就是使用技術(shù)來幫助我們了解重要事項。 缺點可能需要很長時間:某些的交叉和變異可能會對程序的準確性造成負面影響,從而使程序收斂或達到某個損失閾值的速度變慢。。 代碼在對遺傳算法有了一個一些的了解后,我現(xiàn)在可以向你展示這個程序: import randomimport numpy as npfrom IPython.display import clear_outputfrom keras.layers import Reshapefrom keras.layers import Flattenfrom keras.layers import Conv2Dfrom keras.layers import Conv2DTransposefrom keras.layers import LeakyReLUfrom keras.layers import Dropout,Densefrom keras.optimizers import Adamfrom keras.models import Sequentialfrom keras.datasets.mnist import load_data(trainX, trainy), (testX, testy) = load_data() 這里我們使用Keras進行鑒別器部分的構(gòu)建,但是遺傳算法中的神經(jīng)網(wǎng)絡(luò)是以numpy為基礎(chǔ)進行構(gòu)建的。
這是' geneticalgorithm'類的創(chuàng)建,其中包含與遺傳算法有關(guān)的所有功能以及其應(yīng)如何發(fā)揮作用。 主要功能是它以popsize,generations,threshold,network作為參數(shù)。 pop_size是生成的種群的大小,generation是時代的術(shù)語,threshold是損失值的閾值。 X和y用于標記數(shù)據(jù)的遺傳算法。 對于沒有數(shù)據(jù)或未標記數(shù)據(jù)的問題,可以刪除X和y的所有實例。 class neural_network: def __init__(self,network): self.weights = [] self.activations = [] for layer in network: if layer[0] != None: input_size = layer[0] else: input_size = network[network.index(layer)-1][1] output_size = layer[1] activation = layer[2] self.weights.append(np.random.randn(input_size,output_size)) self.activations.append(activation) def propagate(self,data): input_data = data for i in range(len(self.weights)): z = np.dot(input_data,self.weights[i]) a = self.activations[i](z) input_data = a yhat = a return yhat self.neural_network = neural_network(network) self.fitness = 0 這個腳本描述了每個代理的神經(jīng)網(wǎng)絡(luò)的權(quán)值的初始化和網(wǎng)絡(luò)的傳播。
此功能創(chuàng)建將要測試的第一批代理。 def fitness(agents): for agent in agents: dataset_len = 100 fake = [] real = [] y = [] for i in range(dataset_len//2): fake.append(agent.neural_network.propagate(np.random.randn(latent_size)).reshape(28,28)) y.append(0) real.append(random.choice(trainX)) y.append(1) X = fake+real X = np.array(X).astype('uint8').reshape(len(X),28,28,1) y = np.array(y).astype('uint8') model.fit(X,y,verbose = 0) fake = [] real = [] y = [] for i in range(dataset_len//2): fake.append(agent.neural_network.propagate(np.random.randn(latent_size)).reshape(28,28)) y.append(0) real.append(random.choice(trainX)) y.append(1) X = fake+real X = np.array(X).astype('uint8').reshape(len(X),28,28,1) y = np.array(y).astype('uint8') agent.fitness = model.evaluate(X,y,verbose = 0)[1]*100 return agents 適應(yīng)度函數(shù)是此遺傳算法的獨特部分:
(鑒別器的神經(jīng)網(wǎng)絡(luò)將在以后定義。 該模型將根據(jù)之前加載的MNIST數(shù)據(jù)集進行訓(xùn)練。 該模型采用卷積網(wǎng)絡(luò)的形式,以返回二進制結(jié)果) 此功能模仿了進化中的選擇理論:最佳選擇生存,而其他選擇則死亡。 在這種情況下,它們的數(shù)據(jù)將被遺忘并且不再使用。 def unflatten(flattened,shapes): newarray = [] index = 0 for shape in shapes: size = np.product(shape) newarray.append(flattened[index : index + size].reshape(shape)) index += size return newarray 要執(zhí)行交叉和變異功能,需要將權(quán)重展平和展平成原始形狀。
交叉功能是程序中最復(fù)雜的功能之一。 它生成兩個新的'子代'代理,它們的權(quán)重被替換為兩個隨機生成的父代理的交叉。 這是創(chuàng)建權(quán)重的過程: 1. 壓平父母的權(quán)重 1. 產(chǎn)生兩個分裂點 1. 使用拆分點作為索引來設(shè)置兩個子代理的權(quán)重 def mutation(agents): for agent in agents: if random.uniform(0.0, 1.0) <= 0.1: weights = agent.neural_network.weights shapes = [a.shape for a in weights]flattened = np.concatenate([a.flatten() for a in weights]) randint = random.randint(0,len(flattened)-1) flattened[randint] = np.random.randn()newarray = [a ] indeweights = 0 for shape in shapes: size = np.product(shape) newarray.append(flattened[indeweights : indeweights + size].reshape(shape)) indeweights += size agent.neural_network.weights = newarray return agents 這是突變函數(shù)。扁平化與交叉函數(shù)相同。選擇一個隨機的點,用一個隨機的值替換,而不是分割這些點。
這是execute函數(shù)的最后一部分,它執(zhí)行已定義的所有函數(shù)。 image_size = 28latent_size = 100model = Sequential()model.add(Conv2D(64, (3,3), strides=(2, 2), padding='same', input_shape=(image_size,image_size,1)))model.add(LeakyReLU(alpha=0.2))model.add(Dropout(0.4))model.add(Conv2D(64, (3,3), strides=(2, 2), padding='same'))model.add(LeakyReLU(alpha=0.2))model.add(Dropout(0.4))model.add(Flatten())model.add(Dense(1, activation='sigmoid'))opt = Adam(lr=0.0002, beta_1=0.5)model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])network = [[latent_size,100,sigmoid],[None,image_size**2,sigmoid]]ga = genetic_algorithmagent = ga.execute(1000,1000,90,network)(trainX, trainy), (testX, testy) = load_data()weights = agent.neural_network.weights 這就是卷積網(wǎng)絡(luò)實現(xiàn)的鑒別器。Imagesize是MNIST圖像的大小,latentsize用于確保 這將執(zhí)行整個遺傳算法。 對于網(wǎng)絡(luò)變量,每個嵌套列表都包含輸入神經(jīng)元編號,輸出神經(jīng)元編號和激活函數(shù)。 execute函數(shù)返回最佳代理。 總結(jié)顯然,遺傳算法的收斂速度不會像基于梯度的算法那樣快,但計算工作在較長一段時間內(nèi)分散,使它在計算機上不那么密集! |
|
來自: taotao_2016 > 《AI》