Извините за мое невежество, это моя первая попытка с тензорным потоком. Для k-й входной выборки и скорости обучения
я пытаюсь реализовать правило обучения Hebian, заданное,
где с использованием тензорного потока.
После некоторого поиска я нашел этот код, который реализует вариант правила обновления градиента. В этом коде правило обновления не зависит от входных данных. Не могли бы вы подсказать, как настроить этот код (возможно,
_apply_dense
и _create_slots
) для реализации вышеуказанного правила обучения?
Спасибо.
@Влад спасибо за ответ. Да, ввод, я внес правку в пост.
Вы смогли понять мой ответ? Обратите внимание, что вам не нужно создавать подклассы от tf.train.Optimizer
для его реализации.
@ Влад, спасибо за ответ, пожалуйста, дайте мне еще немного, чтобы сделать некоторые заметки.
Пойдем с примером. Предположим, что размер x
равен (None, 2)
, и вы кормите размер партии 4, поэтому размер x
будет (4, 2)
. Предположим также, что форма веса w
равна (2, 2)
.
y=W^Tx
, и нам также придется транспонировать x
, чтобы это можно было сделать: y = tf.matmul(tf.transpose(w), tf.transpose(x))
. Это приведет к форме (2, 2)x(2, 4)-->(2, 4)
.xy^T
. Здесь мы также переместим x
: xyT = tf.matmul(tf.tranpose(x), tf.transpose(y))
, что приведет к форме (2, 4)x(4, 2)--> (2, 2)
.WW^T
, который будет иметь форму (2, 2)
.alpha*(I-WW^T)
, который также будет иметь форму (2, 2)
.xy^T
.Код:
def hebian_update(x, alpha=0.01):
with x.graph.as_default():
weights = tf.trainable_variables()
# 1
y = [tf.matmul(tf.transpose(w), tf.transpose(x)) for w in weights] # y = W^Tx
# 2
xyT = [tf.matmul(tf.transpose(x), tf.transpose(w)) for w in y] # xy^T
# 3
wwT = [tf.matmul(w, tf.transpose(w)) for w in weights] # WW^T
wwTshapes = [w.get_shape().as_list() for w in wwT] # shapes of WW^T
# 4
diffs = [alpha*(tf.eye(num_rows=s[0], num_columns=s[1]) - w)
for w, s in zip(wwT, wwTshapes)] # alpha*(I-WW^T)
# 5
diffs = [tf.matmul(d, w) for d, w in zip(diffs, xyT)] # alpha*(I-WW^T)xy^T
# 6
update_ops = [tf.assign(w, w + d) for w, d in zip(weights, diffs)]
return tf.group(update_ops)
Давайте проверим это с помощью небольшой нейронной сети на наборе данных blobs:
# dataset for illustration
from sklearn.datasets import make_blobs
x_train, y_train = make_blobs(n_samples=4,
n_features=2,
centers=[[1, 1], [-1, -1]],
cluster_std=0.5)
x = tf.placeholder(tf.float32, shape=[None, 2])
y = tf.placeholder(tf.int32, shape=[None])
with tf.name_scope('network'):
fc1 = tf.layers.dense(x, units=2, use_bias=False)
logits = tf.layers.dense(fc1, units=2, use_bias=False)
hebian_op = hebian_update(x)
with tf.name_scope('loss'):
xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
loss_fn = tf.reduce_mean(xentropy)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(loss_fn.eval({x:x_train, y:y_train})) # 0.14356796
_ = sess.run(hebian_op, feed_dict = {x:x_train})
print(loss_fn.eval({x:x_train, y:y_train})) # 0.3619529
Это ваша ответственность теперь, когда все веса в нейронной сети совместимы с вводом x
(т.е. делать y = tf.matmul(tf.transpose(w), tf.transpose(x))
)!
Спасибо еще раз. Думаю, у меня есть несколько вопросов. 1) Почему вы используете итеративные вычисления для основных вычислений? Можно подробнее в этой части? 2) На этапе тестирования, почему вы используете в два раза больше tf.layer.dense
(1, 2) Я дважды использовал tf.layers.dense()
, чтобы показать вам пример сети с более чем одним слоем. Я никогда не слышал об обновлении Hebian и не знаю, используется ли оно для оптимизации нейронных сетей, поэтому я показал вам общий случай, когда нейронная сеть может содержать более одной весовой матрицы (в частности, в моем примере определяется как это w2^T(w1^Tx )
). Если бы у вас была одна, две или более весовых матриц, функция, которую я предоставил, все равно будет работать.
В случае w2^T(w1^Tx)
я обновляю w1
и w2
независимо, поэтому у меня есть обновления как понимание списка - потому что сначала я обновляю w1
, а потом w2
.
Если у вас есть один слой (одна весовая матрица), код все равно будет работать.
Итак, в данном примере есть серия из одной скрытой единицы активации? Я прав?
Вы можете сказать это. matmul
операция w1^Tx
приводит к скрытым единицам (в моем случае без активации), которые являются входными данными для второго слоя. Вывод второго и последнего слоя w2^T(w1^Tx)
не считается содержащим «скрытые» единицы. В тензорном потоке последний слой называется логитом.
Что такое
x
? Это ввод?