(self, D, M, K)
| 86 | |
| 87 | |
| 88 | def build(self, D, M, K): |
| 89 | # params |
| 90 | self.W = tf.Variable(tf.random.normal(shape=(D, K, M)) * np.sqrt(2.0 / M)) |
| 91 | self.c = tf.Variable(np.zeros(M).astype(np.float32)) |
| 92 | self.b = tf.Variable(np.zeros((D, K)).astype(np.float32)) |
| 93 | |
| 94 | # data |
| 95 | self.X_in = tf.compat.v1.placeholder(tf.float32, shape=(None, D, K)) |
| 96 | self.mask = tf.compat.v1.placeholder(tf.float32, shape=(None, D, K)) |
| 97 | |
| 98 | # conditional probabilities |
| 99 | # NOTE: tf.contrib.distributions.Bernoulli API has changed in Tensorflow v1.2 |
| 100 | V = self.X_in |
| 101 | p_h_given_v = tf.nn.sigmoid(dot1(V, self.W) + self.c) |
| 102 | self.p_h_given_v = p_h_given_v # save for later |
| 103 | |
| 104 | # draw a sample from p(h | v) |
| 105 | r = tf.random.uniform(shape=tf.shape(input=p_h_given_v)) |
| 106 | H = tf.cast(r < p_h_given_v, dtype=tf.float32) |
| 107 | |
| 108 | # draw a sample from p(v | h) |
| 109 | # note: we don't have to actually do the softmax |
| 110 | logits = dot2(H, self.W) + self.b |
| 111 | cdist = tf.compat.v1.distributions.Categorical(logits=logits) |
| 112 | X_sample = cdist.sample() # shape is (N, D) |
| 113 | X_sample = tf.one_hot(X_sample, depth=K) # turn it into (N, D, K) |
| 114 | X_sample = X_sample * self.mask # missing ratings shouldn't contribute to objective |
| 115 | |
| 116 | |
| 117 | # build the objective |
| 118 | objective = tf.reduce_mean(input_tensor=self.free_energy(self.X_in)) - tf.reduce_mean(input_tensor=self.free_energy(X_sample)) |
| 119 | self.train_op = tf.compat.v1.train.AdamOptimizer(1e-2).minimize(objective) |
| 120 | # self.train_op = tf.train.GradientDescentOptimizer(1e-3).minimize(objective) |
| 121 | |
| 122 | # build the cost |
| 123 | # we won't use this to optimize the model parameters |
| 124 | # just to observe what happens during training |
| 125 | logits = self.forward_logits(self.X_in) |
| 126 | self.cost = tf.reduce_mean( |
| 127 | input_tensor=tf.nn.softmax_cross_entropy_with_logits( |
| 128 | labels=tf.stop_gradient(self.X_in), |
| 129 | logits=logits, |
| 130 | ) |
| 131 | ) |
| 132 | |
| 133 | # to get the output |
| 134 | self.output_visible = self.forward_output(self.X_in) |
| 135 | |
| 136 | initop = tf.compat.v1.global_variables_initializer() |
| 137 | self.session = tf.compat.v1.Session() |
| 138 | self.session.run(initop) |
| 139 | |
| 140 | def fit(self, X, mask, X_test, mask_test, epochs=10, batch_sz=256, show_fig=True): |
| 141 | N, D = X.shape |
no test coverage detected