日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

【theano-windows】学习笔记十四——堆叠去噪自编码器

發布時間:2023/12/13 windows 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【theano-windows】学习笔记十四——堆叠去噪自编码器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

前面已經學習了softmax,多層感知器,CNN,AE,dAE,接下來可以仿照多層感知器的方法去堆疊自編碼器

國際慣例,參考文獻:

Stacked Denoising Autoencoders (SdA)

Greedy Layer-Wise Training of Deep Networks

理論

通過將降噪自編碼器的低層隱單元輸出作為當前層的輸入,可以把自編碼器堆疊成深度網絡。 這類的無監督預許連方法是逐層展開的。每一層都通過最小化輸入(上一層的輸出編碼)的重構誤差訓練一個降噪自編碼器. 一旦之前的k層被訓練了,我們就可以訓練第k+1層, 因為我們可以計算下一層的隱層表示。

如果所有層都預訓練完畢,就進入第二個階段稱為微調(fine-tuning), 這里由于手頭只有mnist數據集,所以我們就采用有監督微調。首先在預訓練好的網絡頂部添一個softmax層,然后將整個網絡當做多層感知機訓練。

訓練過程包含兩個階段:自編碼器的逐層訓練,多層感知器MLP的整體訓練,這兩個階段是鏈接著的,因為:

  • 自編碼與MLP的sigmoid層是共享參數的,這里的參數說的是權重和偏置
  • MLP的中間層計算得到的特征表示作為自編碼器的輸入

【思考】其實這里感覺的難點在于如何將訓練好的逐層AE參數導入到第二階段的MLP中,剩下的比如怎么建立模型,可以參考MLP(由多隱層和softmax層組成)的寫法.

我個人比較喜歡的代碼風格是, 先定義一些必要的函數(比如讀取數據, 數據預處理等), 然后定義網絡結構(初始化每一層參數), 隨后針對網絡結構進行梯度更新和訓練, 最后測試模型, 所以寫堆疊自編碼的流程大概也是:①定義讀數據函數, ②定義網絡結構③定義預訓練④定義微調⑤測試

代碼

老樣子, 先數據集的讀取函數

import theano import theano.tensor as T import numpy as np import os import cPickle,gzip from theano.tensor.shared_randomstreams import RandomStreams#定義讀數據的函數,把數據丟入到共享區域 def load_data(dataset):data_dir,data_file=os.path.split(dataset)if os.path.isfile(dataset):with gzip.open(dataset,'rb') as f:train_set,valid_set,test_set=cPickle.load(f)#共享數據集def shared_dataset(data_xy,borrow=True):data_x,data_y=data_xyshared_x=theano.shared(np.asarray(data_x,dtype=theano.config.floatX),borrow=borrow)shared_y=theano.shared(np.asarray(data_y,dtype=theano.config.floatX),borrow=borrow)return shared_x,T.cast(shared_y,'int32')#定義三個元組分別存儲訓練集,驗證集,測試集train_set_x,train_set_y=shared_dataset(train_set)valid_set_x,valid_set_y=shared_dataset(valid_set)test_set_x,test_set_y=shared_dataset(test_set)rval=[(train_set_x,train_set_y),(valid_set_x,valid_set_y),(test_set_x,test_set_y)]return rval

然后我們搭建堆疊自編碼器需要有隱層的建立和最后一層的softmax層, 直接copy前面學到的建立方法

對于隱層的代碼

#預訓練需要有隱層 class HiddenLayer(object):def __init__(self,rng,input,n_in,n_out,W=None,b=None,activation=T.tanh):self.input=inputif W is None:W_values=np.asarray(rng.uniform(low=- np.sqrt(6./(n_in+n_out)),high= np.sqrt(6./(n_in+n_out)),size=(n_in,n_out)),dtype=theano.config.floatX)if activation==T.nnet.sigmoid:W_values *= 4W=theano.shared(value=W_values,name='W',borrow=True)if b is None:b_vaules=np.zeros((n_out,),dtype=theano.config.floatX)b=theano.shared(value=b_vaules,name='b',borrow=True)self.W=Wself.b=blin_output=T.dot(input,self.W)+self.b#未被激活的線性操作self.output=(lin_output if activation is None else activation(lin_output))self.params=[self.W,self.b]

然后是softmax層的建立方法

#微調需要softmax class LogisticRegression(object):def __init__(self,input,n_in,n_out):#共享權重self.W=theano.shared(value=np.zeros((n_in,n_out),dtype=theano.config.floatX),name='W',borrow=True)#共享偏置self.b=theano.shared(value=np.zeros((n_out,),dtype=theano.config.floatX),name='b',borrow=True)#softmax函數self.p_y_given_x=T.nnet.softmax(T.dot(input,self.W)+self.b)#預測值self.y_pred=T.argmax(self.p_y_given_x,axis=1)self.params=[self.W,self.b]#模型參數self.input=input#模型輸入#定義負對數似然def negative_log_likelihood(self,y):return -T.mean(T.log(self.p_y_given_x)[T.arange(y.shape[0]),y])#定義誤差def errors(self, y):# check if y has same dimension of y_predif y.ndim != self.y_pred.ndim:raise TypeError('y should have the same shape as self.y_pred',('y', y.type, 'y_pred', self.y_pred.type))# check if y is of the correct datatypeif y.dtype.startswith('int'):# the T.neq operator returns a vector of 0s and 1s, where 1# represents a mistake in predictionreturn T.mean(T.neq(self.y_pred, y))else:raise NotImplementedError()

預訓練過程是逐層按照自編碼訓練, 因為需要自編碼的訓練方法, 同樣copy前面的自編碼建立代碼

#定義自編碼部分 class dA(object):#初始化所需參數,隨機初始化,輸入,輸入單元數,隱單元數, 權重,偏置def __init__(self,rng,input=None,n_visible=784,n_hidden=500,W=None,h_b=None,v_b=None):self.n_visible=n_visibleself.n_hidden=n_hiddenif not W:initial_W=np.asarray(rng.uniform(low=-4*np.sqrt(6./(n_hidden+n_visible)),high=4*np.sqrt(6./(n_hidden+n_visible)),size=(n_visible,n_hidden)),dtype=theano.config.floatX)W=theano.shared(initial_W,name='W',borrow=True)if not h_b:h_b=theano.shared(np.zeros(n_hidden,dtype=theano.config.floatX),borrow=True)if not v_b:v_b=theano.shared(np.zeros(n_visible,dtype=theano.config.floatX),borrow=True)self.W=Wself.vb=v_bself.hb=h_bself.W_prime=self.W.Tif input is None:self.x=T.dmatrix(name='input')else:self.x=inputself.params=[self.W,self.vb,self.hb]#編碼階段def get_hidden_value(self,input):return T.nnet.sigmoid(T.dot(input,self.W)+self.hb)#解碼階段def get_reconstructed_input(self,hidden):return T.nnet.sigmoid(T.dot(hidden,self.W_prime)+self.vb)#是否有損輸入,如果是有損輸入就是降噪自編碼器了def get_corrupted_input(self,input,corruption_level):srng=RandomStreams(np.random.randint(2**30))return srng.binomial(size=input.shape,n=1,p=1-corruption_level,dtype=theano.config.floatX)*input#更新參數def get_cost_updates(self,corruption_level,learning_rate):tilde_x=self.get_corrupted_input(self.x,corruption_level)#有損數據y=self.get_hidden_value(tilde_x)#編碼z=self.get_reconstructed_input(y)#解碼#損失函數L=-T.sum(self.x*T.log(z)+(1-self.x)*T.log(1-z),axis=1)cost=T.mean(L)#參數梯度gparams=T.grad(cost,self.params)#更新權重偏置updates=[(param,param-learning_rate*gparam) for param,gparam in zip(self.params,gparams)]return (cost,updates)

然后重頭戲來了, 根據上面的隱層、softmax層、自編碼層搭建一個堆疊式的多隱層自編碼網絡:

主要包含兩個過程: 預訓練網絡搭建, 整體微調代碼(在預訓練模型頂層加入softmax, 重點過程是如何將預訓練好的模型與微調模型的參數和輸出對接好, 從代碼中很容易分析, 不多說

#初始化整個SdA網絡 class SdA(object):def __init__(self,rng,n_ins=784,n_hiddens=[500,500],n_outs=10):self.sigmoid_layers=[] #存儲每個隱層self.params=[]#存儲每層參數self.dA_layers=[]self.n_hiddens=n_hiddensself.x=T.matrix('x')#存儲輸入self.y=T.ivector('y')#存儲對應標簽for i in range(len(n_hiddens)):if i==0:#當是輸入層的時候input_size=n_insinput=self.xelse :#當是隱層的時候input_size=n_hiddens[i-1]input=self.sigmoid_layers[-1].output#定義當前循環時候的隱層sigmoid_layer=HiddenLayer(rng,input,input_size,n_hiddens[i],activation=T.nnet.sigmoid)#將隱層一層一層堆疊起來self.sigmoid_layers.append(sigmoid_layer)#參數也一層一層存起來self.params.extend(sigmoid_layer.params)#降噪自編碼器的參數與隱單元參數共享dA_layer=dA(rng,input,input_size,n_hiddens[i],W=sigmoid_layer.W,h_b=sigmoid_layer.b)#堆疊降噪自編碼器self.dA_layers.append(dA_layer)######################微調####################在最頂層加一個softmaxself.loglayer=LogisticRegression(self.sigmoid_layers[-1].output,n_hiddens[-1],n_outs)#最終參數self.params.extend(self.loglayer.params)#微調階段的損失self.finetune_cost=self.loglayer.negative_log_likelihood(self.y)#微調階段的誤差self.finetune_err=self.loglayer.errors(self.y)#定義預訓練函數def pre_train(self,train_set,batch_size,corrupt_level=0.2,learning_rate=0.1):index=T.lscalar('index')pretrain_fns=[]#存儲每層的預訓練函數for i,dA in enumerate(self.dA_layers):#對于每一個自編碼層cost,updates=dA.get_cost_updates(corrupt_level[i],learning_rate)#編譯函數fn=theano.function(inputs=[index],outputs=cost,updates=updates,givens={self.x:train_set[index*batch_size:(index+1)*batch_size]})pretrain_fns.append(fn)return pretrain_fns#定義微調部分def fine_tune(self,datasets,batch_size,learning_rate=0.1):train_set_x,train_set_y=datasets[0]#訓練集valide_set_x,valide_set_y=datasets[1]#驗證集test_set_x,test_set_y=datasets[2]#測試集n_train_batches=train_set_x.get_value(borrow=True).shape[0]//batch_size#訓練集每批大小n_valid_batches=valide_set_x.get_value(borrow=True).shape[0]//batch_size#驗證集每批大小n_test_batches=test_set_x.get_value(borrow=True).shape[0]//batch_size#測試集每批大小index=T.lscalar('index')#對所有層參數的梯度gparams=T.grad(self.finetune_cost,self.params)#更新參數updates=[(param,param-gparam*learning_rate) for param,gparam in zip(self.params,gparams)]#訓練過程train_fn=theano.function(inputs=[index],outputs=self.finetune_cost,updates=updates,givens={self.x:train_set_x[batch_size*index:batch_size*(index+1)],self.y:train_set_y[batch_size*index:batch_size*(index+1)]})#驗證過程valid_fn=theano.function(inputs=[index],outputs=self.finetune_err,givens={self.x:valide_set_x[batch_size*index:batch_size*(index+1)],self.y:valide_set_y[batch_size*index:batch_size*(index+1)]})#測試過程test_fn=theano.function(inputs=[index],outputs=self.finetune_err,givens={self.x:test_set_x[batch_size*index:batch_size*(index+1)],self.y:test_set_y[batch_size*index:batch_size*(index+1)]})return train_fn,valid_fn,test_fn

按照流程, 我們就可以定義整個網絡的訓練了,包含數據集的分批, 按照上面定義的網絡結構, 初始化一個網絡實例, 隨后調用上面寫出來的訓練和驗證函數去訓練整個模型, 采用提前停止算法, 前面說過這個算法, 不贅述

#訓練及測試 def test_SdA(pretrain_epoch=1,pretrain_lr=0.001,train_epoch=1,finetune_lr=0.1,dataset='mnist.pkl.gz',batchsize=100):#讀取數據集datasets=load_data(dataset=dataset)train_set_x, train_set_y = datasets[0]valid_set_x, valid_set_y = datasets[1]test_set_x, test_set_y = datasets[2]#總共多少小批次需要訓練n_train_batches=train_set_x.get_value(borrow=True).shape[0]//batchsizen_test_batches=test_set_x.get_value(borrow=True).shape[0]//batchsizen_valid_batches=valid_set_x.get_value(borrow=True).shape[0]//batchsize#初始化SdA網絡rng=np.random.RandomState(1234)sda=SdA(rng,n_ins=28*28,n_hiddens=[1000,1000,1000],n_outs=10)#輸入層和第一二隱層的加噪程度corruption_levels=[0.1,0.2,0.3]############預訓練#############print('############預訓練#############')pretrain_fns=sda.pre_train(train_set_x,batchsize,corrupt_level=corruption_levels,learning_rate=0.1)#對每一層每一小批都執行訓練for i in range(len(sda.n_hiddens)):#對第i層的所有小批執行epoch次訓練for epoch in range(pretrain_epoch):c=[]#記錄總誤差#對每一小批都訓練for batch_index in range(n_train_batches):c.append(pretrain_fns[i](index=batch_index))print('第%d層的第%d次預訓練損失為%f' %(i,epoch,np.mean(c,dtype='float64')))#############微調###############print('#############微調##############')train_fn,valid_fn,test_fn=sda.fine_tune(datasets,batchsize,learning_rate=finetune_lr)#提前停止方法patiences=10000patience_inc=2improvement_threshold=0.995validation_frequency=min(n_train_batches,patiences)best_validation_loss=np.inftest_score=0done_loop=Falsewhile (epoch<train_epoch) and (not done_loop):epoch=epoch+1print epochfor minibatch_index in range(n_train_batches):#對于每一批都訓練minibatch_cost=train_fn(minibatch_index)iter=(epoch-1)*n_train_batches+minibatch_index #累計訓練了多少批,用于決定是否驗證準確率if(iter+1)%validation_frequency==0:validation_loss=np.mean([valid_fn(j) for j in range(n_valid_batches)],dtype='float64')print('訓練第%d次,對于第%d個小批訓練的參數得到誤差為%f' %(epoch,minibatch_index,validation_loss))if validation_loss<best_validation_loss:if validation_loss<best_validation_loss*improvement_threshold:patiences=patiences*patience_incbest_validation_loss=validation_lossbest_iter=iter#驗證集上的誤差為test_score=np.mean([test_fn(k) for k in range(n_test_batches)],dtype='float64')if patiences<=iter:done_loop=Truebreaksave_file=open('best_model_SdA.pkl','wb')model=[sda.params]for i,par in enumerate(model):l=[]for t in range(len(par)):l.append(par[t].get_value())cPickle.dump( l,save_file)print ('最好模型參數的驗證集誤差為%f,測試集誤差%f' %(best_validation_loss,test_score))

最后訓練

test_SdA()

很神奇的是我只對每一層預訓練一次, 最后整體微調也只訓練一次就達到了非常非常非常非常好的效果, 可能內部原因是采用了小批訓練, 結果每一批數據對網絡的參數改變都足夠使它逼近最優處, 所以無需訓練太多, 訓練結果如下

############預訓練#############0層的第0次預訓練損失為75.6216351層的第0次預訓練損失為461.6377592層的第0次預訓練損失為170.258758 #############微調############## 1 訓練第1次,對于第499個小批訓練的參數得到誤差為0.080000 最好模型參數的驗證集誤差為0.080000,測試集誤差0.083700

單張圖片分類

這里有個坑是我原本想使用MLP里面的方法直接調用logistics模型中的pred方法, 結果死活載入不進去圖片, 主要思想如下:

#測試過程 sda=cPickle.load(open('best_model_SdA.pkl'))#讀取模型 #初始化一個用于測試的網絡 sda_test=SdA(rng=np.random.RandomState(1234),n_ins=28*28,n_hiddens=[1000,1000,1000],n_outs=10) #初始化所有權重和偏置 sda_test.sigmoid_layers[0].W.set_value(sda[0]) sda_test.sigmoid_layers[0].b.set_value(sda[1]) sda_test.sigmoid_layers[1].W.set_value(sda[2]) sda_test.sigmoid_layers[1].b.set_value(sda[3]) sda_test.sigmoid_layers[2].W.set_value(sda[4]) sda_test.sigmoid_layers[2].b.set_value(sda[5]) sda_test.loglayer.W.set_value(sda[6]) sda_test.loglayer.b.set_value(sda[7]) #取一張圖片預測 from PIL import Image import pylabdataset='mnist.pkl.gz' datasets=load_data(dataset) test_set_x,test_set_y=datasets[2] test_set_x=test_set_x.get_value() test_data=test_set_x[12:13]predict_model=theano.function(inputs=[x],outputs=classifier_test.logRegressitionLayer.y_pred) predicted_value=predict_model(test_data) print predicted_value

結果這個代碼導數第三行一直提示這個x與需要的輸入不匹配, 逼得我直接使用了最笨的方法, 手動執行前向計算, 需要注意的是我們一定要對自己的前向過程很熟悉, 包括權重每個維度的意義, 偏置和激活函數的使用等等

然后我就寫出了如下代碼:

#測試過程 sda=cPickle.load(open('best_model_SdA.pkl'))#讀取模型 #取一張圖片預測 from PIL import Image import pylabdataset='mnist.pkl.gz' datasets=load_data(dataset) test_set_x,test_set_y=datasets[2] test_set_x=test_set_x.get_value() test_data=test_set_x[12:13] img=test_data.reshape(28,28) pylab.imshow(img) pylab.show()#預測 for i in range(len(sda)/2-1):if i==0:outputs=T.nnet.sigmoid(T.dot(test_data,sda[i])+sda[i+1])else:outputs=T.nnet.sigmoid(T.dot(outputs,sda[i*2])+sda[i*2+1]) #softma層 outputs=T.nnet.softmax(T.dot(outputs,sda[6])+sda[7]) #結果 a=outputs.eval() print np.argmax(a)

部分結果輸出如下:


博客源碼:鏈接: https://pan.baidu.com/s/1mh5AwXi 密碼: gqa4

總結

以上是生活随笔為你收集整理的【theano-windows】学习笔记十四——堆叠去噪自编码器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。