稀疏自编码器_基于tf实现稀疏自编码和在推荐中的应用
稀疏自編碼
自編碼器(Auto-Encoder)顧名思義,即可以利用自身的高階特征編碼自己。自編碼器也是一種神經(jīng)網(wǎng)絡(luò),他的輸入和輸出是一致的,他借助稀疏編碼的思想,目標(biāo)是使用稀疏的一些高階特征重新組合來(lái)重構(gòu)自己。
因此他的特征十分明顯:
- 期望輸入與輸出一致
- 希望使用高階特征來(lái)重構(gòu)自己,而不只是復(fù)制像素點(diǎn)
自編碼器的輸入節(jié)點(diǎn)和輸出節(jié)點(diǎn)的數(shù)量是一致的,但如果只是單純的逐個(gè)復(fù)制輸入節(jié)點(diǎn)則沒(méi)有意義,像前面提到的,自編碼器通常希望使用少量稀疏的高維特征來(lái)重構(gòu)輸入,所以加入幾種限制:
- (1)中間隱含層節(jié)點(diǎn)的數(shù)量。如果中間隱含節(jié)點(diǎn)數(shù)量小于輸入/輸出的數(shù)量,則為一個(gè)降維的過(guò)程。此時(shí)不可能出現(xiàn)復(fù)制所有節(jié)點(diǎn)的情況,只能學(xué)習(xí)數(shù)據(jù)中最重要的特征,將不太相關(guān)的特征去除。如果再加一個(gè)L1正則,則可以根據(jù)懲罰系數(shù)控制隱含節(jié)點(diǎn)的稀疏程度,懲罰系數(shù)越大,學(xué)到特征越稀疏
- (2)給數(shù)據(jù)加入噪聲,變成了Denoising AutoEncoder(去噪自編碼器),將從噪聲中學(xué)習(xí)出數(shù)據(jù)的特征。此時(shí)只有學(xué)習(xí)數(shù)據(jù)頻繁出現(xiàn)的模式和結(jié)構(gòu),將噪聲去除,才可以復(fù)原數(shù)據(jù)。
去噪自編碼器中最常使用的噪聲有:
- 加性高斯噪聲(Additive Gaussian Noise,AGN)
- 用Masking Noise,即有隨機(jī)遮擋的噪聲
- Variational AutoEncoder(VAE)
Xavier initialization
特點(diǎn):根據(jù)某一層網(wǎng)絡(luò)的輸入、輸出節(jié)點(diǎn)數(shù)量自動(dòng)調(diào)整最合適的分布。Xavier讓權(quán)重滿足0均值,同時(shí)方差為,分布可以是均勻分布或者高斯分布。
tf.random_uniform 創(chuàng)造一個(gè) 范圍內(nèi)的均勻分布
def xavier_init(fan_in, fan_out, constant=1): low = -constant * np.sqrt( 6.0 / (fan_in + fan_out)) high = constant * np.sqrt( 6.0 / (fan_in + fan_out)) return tf.random_uniform( (fan_in, fan_out), minval=low, maxval = high, dtype=tf.float32 )稀疏自編碼可以被解釋為
- 如果當(dāng)神經(jīng)元的輸出接近于1的時(shí)候我們認(rèn)為它被激活,而輸出接近于0的時(shí)候認(rèn)為它被抑制,那么使得神經(jīng)元大部分的時(shí)間都是被抑制的限制則被稱(chēng)作稀疏性限制。這里我們假設(shè)的神經(jīng)元的激活函數(shù)是sigmoid函數(shù)。如果你使用tanh作為激活函數(shù)的話,當(dāng)神經(jīng)元輸出為-1的時(shí)候,我們認(rèn)為神經(jīng)元是被抑制的。
只有一個(gè)隱藏層的稀疏自編碼結(jié)構(gòu)如下圖
這時(shí)候隱藏層則是原始特征的另一種表達(dá)形式。
在推薦中的應(yīng)用
一個(gè)大型推薦系統(tǒng),物品的數(shù)量級(jí)為千萬(wàn),用戶(hù)的數(shù)量級(jí)為億。使用稀疏編碼進(jìn)行數(shù)據(jù)降維后,用戶(hù)或者物品均可用一組低維基向量表征,便于存儲(chǔ)計(jì)算,可供在線層實(shí)時(shí)調(diào)用。
在推薦實(shí)踐中,我們主要使用稀疏編碼的方法,輸入用戶(hù)點(diǎn)擊/收藏/購(gòu)買(mǎi)數(shù)據(jù),訓(xùn)練出物品及用戶(hù)的特征向量,具體構(gòu)造自編碼網(wǎng)絡(luò)的方法如下:
輸入層:每首物品的輸入向量為 ,其中表示用戶(hù)是否點(diǎn)擊/收藏/購(gòu)買(mǎi)這個(gè)物品。輸入矩陣為維(包含一個(gè)截距項(xiàng)),為用戶(hù)數(shù)量,為物品數(shù)量。
輸出層:指定為和輸出層一致(無(wú)截距項(xiàng))。
隱藏層:強(qiáng)制指定神經(jīng)元的數(shù)量為個(gè),此時(shí)隱藏層其實(shí)就是物品的低維特征向量,矩陣為()為特征維數(shù)(包含一個(gè)截距項(xiàng)1,之所以保留,是為了可以重構(gòu)出輸出層),為物品數(shù)量。
隱藏層到輸出層的連接。一般的神經(jīng)網(wǎng)絡(luò)中,往往會(huì)忽略隱藏層到輸出層的連接權(quán)重的意義,只是將其作為一個(gè)輸出預(yù)測(cè)的分類(lèi)器;但在自編碼網(wǎng)絡(luò)中,連接層是有實(shí)際意義的。這些權(quán)重作用是將物品特征向量映射到用戶(hù)是否聽(tīng)過(guò)/喜歡該物品,其實(shí)可就是用戶(hù)的低維特征,所以該稀疏網(wǎng)絡(luò)同樣可以學(xué)習(xí)到用戶(hù)的特征矩陣。值得注意的是,當(dāng)網(wǎng)絡(luò)結(jié)構(gòu)為3層時(shí),其目標(biāo)函數(shù)與svd基本一致,算法上是相通的。
tf實(shí)現(xiàn)
代碼閱讀不便,可以參考blog:https://thinkgamer.blog.csdn.net/article/details/106413077
1、引入需要的package
import numpy as npimport sklearn.preprocessing as prepimport tensorflow as tffrom tensorflow.examples.tutorials.mnist import input_data2、定義個(gè)Xavier初始化器
# 定義一個(gè) Xavier初始化器,讓權(quán)重不大不小,正好合適def xavier_init(fan_in, fan_out, constant=1): low = -constant * np.sqrt(6.0 / (fan_in + fan_out)) high = constant * np.sqrt(6.0 / (fan_in + fan_out)) weight = tf.random_uniform( (fan_in, fan_out), minval=low, maxval=high, dtype=tf.float32) return weight3、構(gòu)建融合高斯噪音的稀疏自編碼
class AdditiveGaussianNoiseAutoEncoder(object): # 構(gòu)造函數(shù) def __init__(self, n_input, n_hidden, transfer_function = tf.nn.softplus, optiminzer = tf.train.AdamOptimizer(), scale = 0.1): # 輸入變量數(shù) self.n_input = n_input # 隱含層節(jié)點(diǎn)數(shù) self.n_hidden = n_hidden # 隱含層激活函數(shù) self.transfer_func = transfer_function # 優(yōu)化器,默認(rèn)使用Adma self.optimizer = optiminzer # 高斯噪聲系數(shù),默認(rèn)使用0.1 self.scale = tf.placeholder(tf.float32) self.training_scale = scale # 初始化神經(jīng)網(wǎng)絡(luò)參數(shù) network_weights = self._initialize_weights() # 獲取神經(jīng)網(wǎng)絡(luò)參數(shù) self.weights = network_weights # 初始化輸入的數(shù)據(jù), 數(shù)據(jù)的維度為 n_input 列,行數(shù)未知 self.x = tf.placeholder(tf.float32, [None, self.n_input]) # 計(jì)算隱藏層值,輸入數(shù)據(jù)為融入噪聲的數(shù)據(jù),然后與w1權(quán)重相乘,再加上偏置 self.hidden = self.transfer_func( tf.add( tf.matmul( self.x + scale * tf.random_normal((self.n_input,)), self.weights["w1"] ), self.weights["b1"] ) ) # 計(jì)算預(yù)測(cè)結(jié)果值,將隱藏層的輸出結(jié)果與w2相乘,再加上偏置 self.reconstruction = tf.add( tf.matmul( self.hidden, self.weights["w2"] ), self.weights["b2"] ) # 計(jì)算平方損失函數(shù)(Squared Error) subtract:計(jì)算差值 self.cost = 0.5 * tf.reduce_mean( tf.pow( tf.subtract( self.reconstruction, self.x ), 2.0 ) ) # 定義優(yōu)化方法,這里默認(rèn)使用的是Adma self.optimizer = optiminzer.minimize(self.cost) init = tf.global_variables_initializer() self.sess = tf.Session() self.sess.run(init) # 權(quán)值初始化函數(shù) def _initialize_weights(self): all_weights = dict() all_weights["w1"] = tf.Variable( xavier_init(self.n_input, self.n_hidden) ) all_weights["b1"] = tf.Variable( tf.zeros([self.n_hidden], dtype = tf.float32) ) all_weights["w2"] = tf.Variable( tf.zeros([self.n_hidden, self.n_input], dtype = tf.float32) ) all_weights["b2"] = tf.Variable( tf.zeros([self.n_input], dtype = tf.float32) ) return all_weights # 計(jì)算損失函數(shù)和優(yōu)化器 def partial_fit(self, X): cost, opt = self.sess.run( (self.cost, self.optimizer), feed_dict= {self.x: X, self.scale: self.training_scale} ) return cost # 計(jì)算損失函數(shù) def calc_total_cost(self, X): return self.sess.run( self.cost, feed_dict= {self.x: X, self.scale: self.training_scale} ) # 輸出自編碼器隱含層的輸出結(jié)果,用來(lái)提取高階特征,是三層(輸入層,隱含層,輸出層)的前半部分 def transform(self, X): return self.sess.run( self.hidden, feed_dict= {self.x: X, self.scale: self.training_scale} ) # 將隱含層的輸出作為結(jié)果,復(fù)原原數(shù)據(jù),是整體拆分的后半部分 def generate(self, hidden = None): if hidden is None: hidden = np.random.normal(size= self.weights["b1"]) return self.sess.run( self.reconstruction, feed_dict= {self.hidden: hidden} ) # 構(gòu)建整個(gè)流程,包括:transform和generate def reconstruct(self, X): return self.sess.run( self.reconstruction, feed_dict={self.x: X, self.scale: self.training_scale} ) # 獲取權(quán)重w1 def getWeights(self): return self.sess.run(self.weights['w1']) # 獲取偏值b1 def getBiases(self): return self.sess.run(self.weights['b1'])4、定義模型訓(xùn)練類(lèi)
class ModelTrain: def __init__(self, training_epochs = 20, batch_size = 128, display_step = 1): self.mnist = self.load_data() # 格式化訓(xùn)練集和測(cè)試集 self.x_train, self.x_test = self.standard_scale(self.mnist.train.images, self.mnist.test.images) # 總的訓(xùn)練樣本數(shù) self.n_samples = int(self.mnist.train.num_examples) # 訓(xùn)練次數(shù) self.training_epochs = training_epochs # 每次訓(xùn)練的批大小 self.batch_size = batch_size # 設(shè)置每多少輪顯示一次loss值 self.display_step = display_step # 加載數(shù)據(jù)集 def load_data(self): return input_data.read_data_sets("../MNIST_data", one_hot=True) # 數(shù)據(jù)標(biāo)準(zhǔn)化處理函數(shù) def standard_scale(self, x_train, x_test): # StandardScaler: z = (x - u) / s (u 均值, s 標(biāo)準(zhǔn)差) preprocessor = prep.StandardScaler().fit(x_train) x_train = preprocessor.transform(x_train) x_test = preprocessor.transform(x_test) return x_train, x_test # 最大限度不重復(fù)的獲取數(shù)據(jù) def get_random_block_from_data(self, data, batch_size): start_index = np.random.randint(0, len(data) - batch_size) return data[start_index:(start_index + batch_size)]5、主函數(shù)調(diào)用進(jìn)行模型訓(xùn)練
if __name__ == "__main__": autoencoder = AdditiveGaussianNoiseAutoEncoder( n_input=784, n_hidden= 200, transfer_function=tf.nn.softplus, optiminzer= tf.train.AdamOptimizer(learning_rate=0.01), scale= 0.01 ) modeltrain = ModelTrain(training_epochs= 20, batch_size= 128, display_step= 1) for epoch in range(modeltrain.training_epochs): avg_cost = 0 # 一共計(jì)算多少次數(shù)據(jù)集 total_bacth = int(modeltrain.n_samples / modeltrain.batch_size) for i in range(total_bacth): batch_x = modeltrain.get_random_block_from_data(modeltrain.x_train, modeltrain.batch_size) cost = autoencoder.partial_fit(batch_x) avg_cost += cost / modeltrain.n_samples * modeltrain.batch_size if epoch % modeltrain.display_step == 0: print("Epoch:", '%04d' % (epoch + 1), "cost=", "{:.9f}".format(avg_cost)) print("Total cost: " + str(autoencoder.calc_total_cost(modeltrain.x_test)))創(chuàng)作不易,點(diǎn)個(gè)“在看”鼓勵(lì)鼓勵(lì)吧總結(jié)
以上是生活随笔為你收集整理的稀疏自编码器_基于tf实现稀疏自编码和在推荐中的应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 计算机二级python分值_计算机二级p
- 下一篇: tensorflow saver_Ten