Я пытаюсь реализовать рекуррентную нейронную сеть с помощью numpy.
Мои текущие схемы ввода и вывода следующие:
x имеет форму: (длина последовательности, размер партии, размер ввода)
h: (количество слоев, количество направлений, размер пакета, скрытый размер)
initial weight: (количество направлений, 2 * скрытый размер, размер ввода + скрытый размер)
weight: (количество слоев -1, количество направлений, скрытый размер, направления * скрытый размер + скрытый размер)
bias: (количество слоев, количество направлений, скрытый размер)
Я просмотрел API-интерфейс pytorch для RNN в качестве ссылки (https://pytorch.org/docs/stable/nn.html?highlight=rnn#torch.nn.RNN), но немного изменил его, чтобы включить исходный вес в качестве входных данных. (выходные формы предположительно такие же, как в pytorch)
Пока он работает, я не могу определить, правильно ли он ведет себя, поскольку я ввожу случайно сгенерированные числа в качестве входных данных.
В частности, я не уверен, правильно ли спроектированы мои входные формы.
Может ли какой-нибудь эксперт дать мне совет?
def rnn(xs, h, w0, w=None, b=None, num_layers=2, nonlinearity='tanh', dropout=0.0, bidirectional=False, training=True):
num_directions = 2 if bidirectional else 1
batch_size = xs.shape[1]
input_size = xs.shape[2]
hidden_size = h.shape[3]
hn = []
y = [None]*len(xs)
for l in range(num_layers):
for d in range(num_directions):
if l==0 and d==0:
wi = w0[d, :hidden_size, :input_size].T
wh = w0[d, hidden_size:, input_size:].T
wi = np.reshape(wi, (1,)+wi.shape)
wh = np.reshape(wh, (1,)+wh.shape)
else:
wi = w[max(l-1,0), d, :, :hidden_size].T
wh = w[max(l-1,0), d, :, hidden_size:].T
for i,x in enumerate(xs):
if l==0 and d==0:
ht = np.tanh(np.dot(x, wi) + np.dot(h[l, d], wh) + b[l, d][np.newaxis])
ht = np.reshape(ht,(batch_size, hidden_size)) #otherwise, shape is (bs,1,hs)
else:
ht = np.tanh(np.dot(y[i], wi) + np.dot(h[l, d], wh) + b[l, d][np.newaxis])
y[i] = ht
hn.append(ht)
y = np.asarray(y)
y = np.reshape(y, y.shape+(1,))
return np.asarray(y), np.asarray(hn)
@ Дэвид какие-нибудь простые фиктивные данные для проверки?
Вы можете проверить UCI, но простой может быть просто посмотреть, может ли он изучить сложение (например, 1-> 2-> 3 ...)
@David, но как это вписывается в дизайн ввода выше? Например, если вы изучали сложение, как оно должно вписываться в форму x (seq_len, batch_size, input_size) и каковы должны быть результаты?
Вы пытаетесь реализовать RNN, не зная, что такое машинное обучение, или даже не выполнив сначала простой классификатор?
@ Дэвид, очевидно, я не понимаю, как настроить форму. Мне грустно видеть снисходительный ответ.
Дополнительное обучение будет просто вводить 1 в модель, а затем модель должна выплюнуть 2. Это возвращается, и модель выплевывает 3 и т. д. Ваш комментарий дает понять, что вам что-то не хватает в том, как работают RNN, поскольку это кажется что вы не поняли, что означает дополнительное обучение.






Что касается формы, это, вероятно, имеет смысл, если это то, как PyTorch делает это, но способ Tensorflow немного более интуитивно понятен - последовательности (batch_size, seq_length, input_size) - batch_size длиной seq_length, где каждый элемент имеет размер input_size. Оба подхода могут работать, так что я думаю, это вопрос предпочтений.
Чтобы увидеть, правильно ли ведет себя ваш rnn, я бы просто распечатал скрытое состояние на каждом временном шаге, запустил его на некоторых небольших случайных данных (например, 5 векторов, по 3 элемента в каждом) и сравнил результаты с вашими ручными вычислениями.
Глядя на ваш код, я не уверен, что он делает то, что должен, но вместо того, чтобы делать это самостоятельно на основе существующего API, я бы рекомендовал вам прочитать и попытаться воспроизвести это потрясающее руководство от wildml (в части 2 есть чистый numpy выполнение).
Если вы пытаетесь определить, обучается ли он, вам следует использовать набор данных и посмотреть, сводит ли он к минимуму цель. По сути, это первый шаг отладки модели.