| 54 | return np.array([self.get_cost(x) for x in X]) |
| 55 | |
| 56 | def build(self, preSoftmaxPi, preSoftmaxA, preSoftmaxB): |
| 57 | M, V = preSoftmaxB.shape |
| 58 | |
| 59 | self.preSoftmaxPi = tf.Variable(preSoftmaxPi) |
| 60 | self.preSoftmaxA = tf.Variable(preSoftmaxA) |
| 61 | self.preSoftmaxB = tf.Variable(preSoftmaxB) |
| 62 | |
| 63 | pi = tf.nn.softmax(self.preSoftmaxPi) |
| 64 | A = tf.nn.softmax(self.preSoftmaxA) |
| 65 | B = tf.nn.softmax(self.preSoftmaxB) |
| 66 | |
| 67 | # define cost |
| 68 | self.tfx = tf.placeholder(tf.int32, shape=(None,), name='x') |
| 69 | def recurrence(old_a_old_s, x_t): |
| 70 | old_a = tf.reshape(old_a_old_s[0], (1, M)) |
| 71 | a = tf.matmul(old_a, A) * B[:, x_t] |
| 72 | a = tf.reshape(a, (M,)) |
| 73 | s = tf.reduce_sum(a) |
| 74 | return (a / s), s |
| 75 | |
| 76 | # remember, tensorflow scan is going to loop through |
| 77 | # all the values! |
| 78 | # we treat the first value differently than the rest |
| 79 | # so we only want to loop through tfx[1:] |
| 80 | # the first scale being 1 doesn't affect the log-likelihood |
| 81 | # because log(1) = 0 |
| 82 | alpha, scale = tf.scan( |
| 83 | fn=recurrence, |
| 84 | elems=self.tfx[1:], |
| 85 | initializer=(pi*B[:,self.tfx[0]], np.float32(1.0)), |
| 86 | ) |
| 87 | |
| 88 | self.cost = -tf.reduce_sum(tf.log(scale)) |
| 89 | self.train_op = tf.train.AdamOptimizer(1e-2).minimize(self.cost) |
| 90 | |
| 91 | def init_random(self, V): |
| 92 | preSoftmaxPi0 = np.zeros(self.M).astype(np.float32) # initial state distribution |