2016-01-13 103 views
9

我試圖用tensorflow實施RBM RBM實施,這裏是代碼:與tensorflow

rbm.py

""" An rbm implementation for TensorFlow, based closely on the one in Theano """ 
import tensorflow as tf 
import math 
def sample_prob(probs): 
    return tf.nn.relu(
     tf.sign(
      probs - tf.random_uniform(probs.get_shape()))) 
class RBM(object): 
    def __init__(self, name, input_size, output_size): 
     with tf.name_scope("rbm_" + name): 
      self.weights = tf.Variable(
       tf.truncated_normal([input_size, output_size], 
        stddev=1.0/math.sqrt(float(input_size))), name="weights") 
      self.v_bias = tf.Variable(tf.zeros([input_size]), name="v_bias") 
      self.h_bias = tf.Variable(tf.zeros([output_size]), name="h_bias") 

    def propup(self, visible): 
     return tf.nn.sigmoid(tf.matmul(visible, self.weights) + self.h_bias) 

    def propdown(self, hidden): 
     return tf.nn.sigmoid(tf.matmul(hidden, tf.transpose(self.weights)) + self.v_bias) 

    def sample_h_given_v(self, v_sample): 
     return sample_prob(self.propup(v_sample)) 

    def sample_v_given_h(self, h_sample): 
     return sample_prob(self.propdown(h_sample)) 

    def gibbs_hvh(self, h0_sample): 
     v_sample = self.sample_v_given_h(h0_sample) 
     h_sample = self.sample_h_given_v(v_sample) 
     return [v_sample, h_sample] 

    def gibbs_vhv(self, v0_sample): 
     h_sample = self.sample_h_given_v(v0_sample) 
     v_sample = self.sample_v_given_h(h_sample) 
     return [h_sample, v_sample] 

    def cd1(self, visibles, learning_rate=0.1): 
     h_start = self.propup(visibles) 
     v_end = self.propdown(h_start) 
     h_end = self.propup(v_end) 
     w_positive_grad = tf.matmul(tf.transpose(visibles), h_start) 
     w_negative_grad = tf.matmul(tf.transpose(v_end), h_end) 
     update_w = self.weights.assign_add(learning_rate * (w_positive_grad - w_negative_grad)) 
     update_vb = self.v_bias.assign_add(learning_rate * tf.reduce_mean(visibles - v_end, 0)) 
     update_hb = self.h_bias.assign_add(learning_rate * tf.reduce_mean(h_start - h_end, 0)) 
     return [update_w, update_vb, update_hb] 

    def reconstruction_error(self, dataset): 
     err = tf.stop_gradient(dataset - self.gibbs_vhv(dataset)[1]) 
     return tf.reduce_sum(err * err) 

rbm_MNIST_test.py

import tensorflow as tf 
import numpy as np 
import rbm 
import input_data 

def build_model(X, w1, b1, wo, bo): 
    h1 = tf.nn.sigmoid(tf.matmul(X, w1)+b1) 
    model = tf.nn.sigmoid(tf.matmul(h1, wo)+bo) 
    return model 

def init_weight(shape): 
    return tf.Variable(tf.random_normal(shape, mean=0.0, stddev=0.01)) 

def init_bias(dim): 
    return tf.Variable(tf.zeros([dim])) 

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) 
trX, trY, teX, teY = mnist.train.images, mnist.train.labels, mnist.test.images, mnist.test.labels 

X = tf.placeholder("float", [None, 784]) 
Y = tf.placeholder("float", [None, 10]) 

rbm_layer = rbm.RBM("mnist", 784, 500) 

for i in range(10): 
    print "RBM CD: ", i 
    rbm_layer.cd1(trX) 

rbm_w, rbm_vb, rbm_hb = rbm_layer.cd1(trX) 


wo = init_weight([500,10]) 
bo = init_bias(10) 
py_x = build_model(X, rbm_w, rbm_hb, wo, bo) 

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(py_x, Y)) 
train_op = tf.train.GradientDescentOptimizer(0.05).minimize(cost) 
predict_op = tf.argmax(py_x, 1) 

sess = tf.Session() 
init = tf.initialize_all_variables() 
sess.run(init) 

for i in range(10): 
    for start, end in zip(range(0, len(trX), 128), range(128, len(trX), 128)): 
     sess.run(train_op, feed_dict={X: trX[start:end], Y: trY[start:end]}) 
    print i, np.mean(np.argmax(teY, axis=1) == 
        sess.run(predict_op, feed_dict={X: teX, Y: teY})) 

,但來這裏的錯誤:

File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py", line 1626, in as_graph_def raise ValueError("GraphDef cannot be larger than 2GB.") ValueError: GraphDef cannot be larger than 2GB.

有人能幫我解決這個問題?

回答

12

TensorFlow在GraphDef原型上的限制爲2GB,這是源於協議緩衝區實現的限制。如果圖中有大的常量張量,則可以快速達到該極限。特別是,如果您多次使用相同的 numpy陣列,TensorFlow會爲您的圖形添加多個常量張量。

在你的情況下,由input_data.read_data_sets返回的mnist.train.images是一個numpy浮點數組,形狀爲(55000, 784),所以它約爲164 MB。您將該numpy數組傳遞給rbm_layer.cd1,並在該函數內部,每次使用visibles時,將從numpy數組創建一個TensorFlow Const節點。您在3個位置使用visibiles,因此每撥打cd1將增加圖表大小約492 MB,因此您很容易超出限制。解決的辦法是創建一次TensorFlow不變並傳遞不斷向cd1功能,像這樣:

trX_constant = tf.constant(trX) 
for i in range(10): 
    print "RBM CD: ", i 
    rbm_layer.cd1(trX_constant) 

BTW,我不知道你的意圖是在上面的循環是什麼。請注意,cd1函數只是簡單地將assign_add節點添加到圖中,並不實際執行分配。如果你真的希望這些分配在你訓練時發生,你應該考慮把這些分配通過控制依賴關係鏈接到你最終的節點上。

4

爲了實現@ keveman的問題,我認爲你正試圖通過使用該循環來實現CD-k(Contrastive Divergence)步驟。

但我怕的代碼是從合適到目前爲止,因爲CD-k是應該採取RBM自動分化的位置的功能。這意味着costtrain_op不是正確的方式與梯度下降RBM(這是因爲CD-k的特殊作用)使用。順便說一句,RBM層應該被逐個訓練而不需要完全連接層這不在你的代碼中。

我是tensorflow的新手,我也想要實現。我想我寧願不使用由tensorflow提供的梯度下降,因爲我需要CD-k進行特殊分化。希望我能儘快找到解決方案。

更新: 我已經在這個實施上工作了整整一個工作日。所以,這是目前的狀態。我已經實現了一個簡單直接的版本,但它只是得到錯誤的結果。 請參考code and result

我只是指從DeepLearnToolbox的具體方法。我認爲我試圖通過tensorflow實現的過程沒問題,但不知道實際代碼出了什麼問題。

更新2:我修改了代碼,現在我通過張量流實現了最簡單的rbm。請參閱上面的code and result鏈接。