Как построить модель в MXNet с использованием матриц и матричных операций?
Я могу создать модель, используя предварительно построенные высокоуровневые функции, такие как FullyConnected
. Например:
X = mx.sym.Variable('data')
P = mx.sym.FullyConnected(data = X, name = 'fc1', num_hidden = 2)
Таким образом, я получаю символическую переменную P
, которая зависит от символической переменной X
. Другими словами, у меня есть вычислительный граф, который можно использовать для определения модели и выполнения таких операций, как fit
и predict
.
Теперь я хотел бы выразить P
через X
по-другому. Более подробно, вместо использования высокоуровневой функциональности (например, FullyConnected
), я хотел бы явно указать отношения между P
и X
", используя низкоуровневые тензорные операции (например, матричное умножение) и символические переменные, представляющие параметры модели (матрица веса озера).
Например, чтобы достичь того же, что и выше, я попробовал followig:
W = mx.sym.Variable('W')
B = mx.sym.Variable('B')
P = mx.sym.broadcast_plus(mx.sym.dot(X, W), B)
Однако полученный таким образом P
не эквивалентен ранее полученному P
. Я не могу использовать его таким же образом. В частности, насколько я понимаю, MXNet жалуется, что W
и B
не имеют значений (что имеет смысл).
Я также попытался объявить W
и B
другим способом (чтобы они имели значения):
w = np.array([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])
b = np.array([7.0, 8.0])
W = mx.nd.array(w)
B = mx.nd.array(b)
Это не работает. Я предполагаю, что MXNet жалуется, потому что он ожидает символическую переменную, но вместо этого получает nd-массивы.
Итак, мой вопрос заключается в том, как построить модель с использованием низкоуровневых тензорных операций (например, матричное умножение) и явных объектов, представляющих параметры модели (например, матричные весы).
Ответы
Ответ 1
Возможно, вы захотите взглянуть на API Gluon. Например, здесь приведено руководство по созданию MLP с нуля, включая выделение параметров:
#######################
# Allocate parameters for the first hidden layer
#######################
W1 = nd.random_normal(shape=(num_inputs, num_hidden), scale=weight_scale, ctx=model_ctx)
b1 = nd.random_normal(shape=num_hidden, scale=weight_scale, ctx=model_ctx)
params = [W1, b1, ...]
Прикрепление их к автоматическому градиенту
for param in params:
param.attach_grad()
Определите модель:
def net(X):
#######################
# Compute the first hidden layer
#######################
h1_linear = nd.dot(X, W1) + b1
...
и выполнить его
epochs = 10
learning_rate = .001
smoothing_constant = .01
for e in range(epochs):
...
for i, (data, label) in enumerate(train_data):
data = data.as_in_context(model_ctx).reshape((-1, 784))
label = label.as_in_context(model_ctx)
...
with autograd.record():
output = net(data)
loss = softmax_cross_entropy(output, label_one_hot)
loss.backward()
SGD(params, learning_rate)
Вы можете увидеть полный пример в прямом допинге:
http://gluon.mxnet.io/chapter03_deep-neural-networks/mlp-scratch.html