#tensorflow #pytorch
Вопрос:
У меня есть быстрый (и, возможно, глупый) вопрос о том, как Tensorflow определяет свой линейный слой. В PyTorch линейный (или плотный) слой определяется как y = x A^T b, где A и b-матрица веса и вектор смещения для линейного слоя (см. Здесь).
Однако я не могу точно найти эквивалентное уравнение для тензорного потока! Это то же самое, что и PyTorch, или это просто y = x A b ?
Заранее благодарю вас!
Ответ №1:
Если мы установим активацию None
в плотном слое в keras
API, то они технически эквивалентны.
Тензорный поток
tf.keras.layers.Dense(..., activation=None)
Согласно доктору, здесь больше исследований.
активация: Функция активации для использования. Если вы ничего не укажете, активация не будет применена (т. е. «линейная» активация: a(x) = x).
И в src Пайторча.
torch.nn.Linear
На данный момент они равны. Линейное преобразование входящих данных: y = x*W^T b
. Смотрите следующую более конкретную эквивалентную реализацию этих двух. В PyTorch
, мы делаем
class Network(torch.nn.Module):
def __init__(self):
super(Network, self).__init__()
self.fc1 = torch.nn.Linear(5, 30)
def forward(self, state):
return self.fc1(state)
или,
trd = torch.nn.Linear(in_features = 3, out_features = 30)
y = trd(torch.ones(5, 3))
print(y.size())
# torch.Size([5, 30])
Его эквивалентная tf
реализация была бы
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(30, input_shape=(5,), activation=None))
или,
tfd = tf.keras.layers.Dense(30, input_shape=(3,), activation=None)
x = tfd(tf.ones(shape=(5, 3)))
print(x.shape)
# (5, 30)
Комментарии:
1. То, что я имею в виду с точки зрения различий, относится исключительно к линейной алгебре операции. А не просто форма выходного тензора. Например, кажется, что плотный слой Tensorflow равен либо y = xA b, либо y = Ax b, а линейный слой PyTorch равен y = xA^T b. Хотя они имеют одинаковую форму, их производные отличаются.
2. О, я понимаю. Название вопроса смутило меня. Похоже, вы хотели знать, как они рассчитываются. Ответ Алекса должен вас устраивать.
3. Да, я мог бы сформулировать это немного лучше. Но, несмотря на это, мне просто нужно было прояснить саму Линейную алгебру и то, как эти слои различаются между Линейными. Производная является одним из примеров того, как они отличаются ( поскольку это разные линейные операции альграбры ). Я высказал «предположение» о том, что такое плотный слой TF и совпадает ли он. Итак, я мог бы отредактировать название, если другие люди подумают, что это поможет с разъяснением! Тем не менее, спасибо за объяснение плотного слоя TF! 😀
Ответ №2:
tf.keras.layers.Dense
определяется здесь в исходном коде tensorflow:
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/keras/layers/core.py#L1081
Если вы будете следовать ссылкам в его call
функции, это приведет вас к определению используемой здесь операции, которая действительно представляет собой матричное умножение входных данных и весов плюс вектор смещения, как и ожидалось:
outputs = gen_math_ops.MatMul(a=inputs, b=kernel)
...
outputs = nn_ops.bias_add(outputs, bias)
Комментарии:
1. Итак, определение
kernel
переменной-это матрица веса, но противоположного измерения матрицы веса PyTorch? Итак, допустим, у меня есть входные функции размера пакета N и выходные функции B. Размерностьkernel
будет [A, B], тогда как в случае PyTorch это будет [B, A] (потому что к нему применяется транспонирование?)2. Да, они хранят веса немного по-разному (W. T против W), но результат все равно тот же. Представление Пайторча ближе к обозначениям в учебниках. Вы можете быстро проверить это, распечатав форму линейных/плотных весов в torch и tf.
3. В строке 1192 первой ссылки на исходный код TF выше веса в инициализируются с
shape=[last_dim, self.units]
помощью (N_feats, N_out), а в PyTorch (ссылка на исходный код) веса инициализируются сParameter(torch.Tensor(out_features, in_features))
помощью (N_out, N_feats)4. Хорошо, поэтому для линейного слоя ввода x формы (N_samp, N_feats) выводом для TF будет matmul(x, A) b, где A (N_feats, N_out) и b (N_out,), а для PyTorch это matmul(x, A^T) b, где A сейчас (N_out, N_feats) и b (N_out,). Хорошо, похоже, что 2 библиотеки определяют свои линейные слои по-разному! Спасибо @Alex!