Также проверьте LSTM

Это чистая реализация генерации слов с использованием RNN

Мы собираемся научить нашу сеть предсказывать следующие слова в данном абзаце. Это потребует повторяющейся архитектуры, поскольку сеть должна будет запоминать последовательность символов. Порядок имеет значение. 1000 итераций, и у нас будет произносимый английский. Чем больше время тренировки, тем лучше. Вы можете кормить его любой текстовой последовательностью (слова, Python, HTML и т. Д.)

Что такое рекуррентная сеть?

Сети прямого распространения отлично подходят для изучения закономерностей между набором входов и выходов.

  • температура и местоположение
  • высота вес
  • скорость и марка машины

Но что, если порядок данных имеет значение?

Алфавит, текст песни. Они хранятся с использованием условной памяти. Вы можете получить доступ к элементу, только если у вас есть доступ к предыдущим элементам (например, к связанному списку).

Войдите в повторяющиеся сети

Мы передаем скрытое состояние из предыдущего временного шага обратно в сеть на следующем временном шаге.

Итак, вместо того, чтобы операция потока данных происходила так

ввод - ›скрытый -› вывод

бывает вот так

(input + prev_hidden) - ›hidden -› output

ждать. Почему не это?

(ввод + пред_ввод) - ›скрытый -› вывод

Скрытое повторение изучает, что нужно помнить, тогда как повторение ввода жестко запрограммировано, чтобы просто помнить непосредственно предыдущую точку данных

Формула RNN

Он в основном говорит, что текущее скрытое состояние h (t) является функцией f предыдущего скрытого состояния h (t-1) и текущего входа x (t). Тета - это параметры функции f. Сеть обычно учится использовать h (t) как своего рода сводку с потерями релевантных для задачи аспектов прошлой последовательности входных данных до t.

Функция потерь

Общие потери для данной последовательности значений x в паре с последовательностью значений y будут тогда просто суммой потерь за все временные шаги. Например, если L (t) - отрицательная логарифмическая вероятность y (t) при x (1),. . . , x (t), затем суммируйте их, вы получите потерю для последовательности

Наши шаги

  • Инициализировать веса случайным образом
  • Дайте модели пару символов (входной символ и целевой символ. Целевой символ - это символ, который сеть должна угадать, это следующий символ в нашей последовательности)
  • Прямой проход (мы рассчитываем вероятность для каждого возможного следующего символа в соответствии с состоянием модели, используя параметры)
  • Ошибка измерения (расстояние между предыдущей вероятностью и целевым символом)
  • Мы рассчитываем градиенты для каждого из наших параметров, чтобы увидеть их влияние на потери (обратное распространение во времени).
  • обновлять все параметры по направлению с помощью градиентов, которые помогают минимизировать потери
  • Повторить! Пока наша потеря невелика AF

Какие варианты использования?

  • Прогнозирование временных рядов (прогноз погоды, цены на акции, объем трафика и т. Д.)
  • Последовательная генерация данных (музыка, видео, аудио и т. Д.)

Другие примеры

-Https: //github.com/anujdutt9/RecurrentNeuralNetwork (двоичное сложение)

Что дальше?

1 Сети LSTM 2 Двунаправленные сети 3 рекурсивные сети

Код состоит из 4 частей

  • Загрузите данные обучения
  • кодировать символы в векторы
  • Определите рекуррентную сеть
  • Определите функцию потерь
  • Вперед пас
  • Потеря
  • Обратный проход
  • Определите функцию для создания предложений из модели
  • Обучите сеть
  • Накормите сеть
  • Рассчитать градиент и обновить параметры модели
  • Выведите текст, чтобы увидеть, как идет обучение

Загрузите обучающие данные

Сеть нуждается в большом текстовом файле в качестве входных данных.

Содержимое файла будет использовано для обучения сети.

Я использую Methamorphosis от Kafka (Public Domain). Потому что Кафка был странным чуваком. Мне нравится.

In [3]:

data = open('kafka.txt', 'r').read()
chars = list(set(data)) 
data_size, vocab_size = len(data), len(chars)
print 'data has %d chars, %d unique' % (data_size, vocab_size)
data has 137629 chars, 81 unique

Кодировать / декодировать символ / вектор

Нейронные сети работают с векторами (вектор - это массив с плавающей запятой). Итак, нам нужен способ кодирования и декодирования символа как вектора.

Мы посчитаем количество уникальных символов (vocab_size). Это будет размер вектора. Вектор содержит только ноль, за исключением положения символа, значение которого равно 1.

Итак, сначала давайте вычислим vocab_size:

In [5]:

char_to_ix = { ch:i for i,ch in enumerate(chars)}
ix_to_char = { i:ch for i, ch in enumerate(chars)}
print char_to_ix
print ix_to_char
{'\n': 0, 'C': 31, '!': 3, ' ': 4, '"': 5, '%': 6, '$': 7, "'": 8, ')': 9, '(': 10, '*': 11, '-': 12, ',': 13, '/': 2, '.': 15, '1': 16, '0': 17, '3': 18, '2': 19, '5': 20, '4': 21, '7': 22, '6': 23, '9': 24, '8': 25, ';': 26, ':': 27, '?': 28, 'A': 29, '@': 30, '\xc3': 1, 'B': 32, 'E': 33, 'D': 34, 'G': 35, 'F': 36, 'I': 37, 'H': 38, 'K': 39, 'J': 40, 'M': 41, 'L': 42, 'O': 43, 'N': 44, 'Q': 45, 'P': 46, 'S': 47, 'R': 48, 'U': 49, 'T': 50, 'W': 51, 'V': 52, 'Y': 53, 'X': 54, 'd': 59, 'a': 55, 'c': 56, 'b': 57, 'e': 58, '\xa7': 14, 'g': 60, 'f': 61, 'i': 62, 'h': 63, 'k': 64, 'j': 65, 'm': 66, 'l': 67, 'o': 68, 'n': 69, 'q': 70, 'p': 71, 's': 72, 'r': 73, 'u': 74, 't': 75, 'w': 76, 'v': 77, 'y': 78, 'x': 79, 'z': 80}
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-5-83f18c934ed8> in <module>()
      2 ix_to_char = { i:ch for i, ch in enumerate(chars)}
      3 print char_to_ix
----> 4 print char_to_char
NameError: name 'char_to_char' is not defined

Затем мы создаем 2 словаря для кодирования и декодирования char в int

In [ ]:

Наконец, мы создаем вектор из символа следующим образом:

Словарь, определенный выше, позволяет нам создать вектор размером 61 вместо 256.
Здесь и пример char 'a'
Вектор содержит только нули, за исключением позиции char_to_ix ['a'], где ставим 1.

In [7]:

import numpy as np
vector_for_char_a = np.zeros((vocab_size, 1))
vector_for_char_a[char_to_ix['a']] = 1
print vector_for_char_a.ravel()
[ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.
  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.
  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.
  0.  1.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.
  0.  0.  0.  0.  0.  0.  0.  0.  0.]

Определение сети

Нейронная сеть состоит из 3-х слоев:

  • входной слой
  • скрытый слой
  • выходной слой

Все слои полностью связаны со следующим: каждый узел слоя связан со всеми узлами следующего слоя. Скрытый слой связан с выходом и сам с собой: значения из итерации используются для следующей.

Чтобы централизовать значения, которые имеют значение для обучения (гиперпараметры), мы также определяем длину последовательности и скорость обучения

In [9]:

#hyperparameters
File "<ipython-input-9-695b49af656c>", line 5
    learning_rate 1e-1
                     ^
SyntaxError: invalid syntax

In [12]:

#model parameters
hidden_size = 100
seq_length = 25
learning_rate = 1e-1
Wxh = np.random.randn(hidden_size, vocab_size) * 0.01 #input to hidden
Whh = np.random.randn(hidden_size, hidden_size) * 0.01 #input to hidden
Why = np.random.randn(vocab_size, hidden_size) * 0.01 #input to hidden
bh = np.zeros((hidden_size, 1))
by = np.zeros((vocab_size, 1))

Параметры модели настраиваются в процессе обучения.

  • Wxh - это параметры для соединения вектора, который содержит один вход, со скрытым слоем.
  • Какие параметры для подключения скрытого слоя к самому себе. Это Ключ Rnn: Рекурсия выполняется путем внедрения предыдущих значений из вывода скрытого состояния в себя на следующей итерации.
  • Почему - это параметры для подключения скрытого слоя к выходу
  • bh содержит скрытую предвзятость
  • by содержит смещение вывода

В следующем разделе вы увидите, как эти параметры используются для создания предложения.

Определите функцию потерь

Потеря является ключевым понятием при обучении всех нейронных сетей. Это значение, которое описывает, насколько хороша наша модель.
Чем меньше потеря, тем лучше наша модель.
(Хорошая модель - это модель, в которой прогнозируемый результат близок к результату обучения)

На этапе обучения мы хотим минимизировать потери.

Функция потерь вычисляет потери, но также и градиенты (см. Обратный проход):

  • Он выполняет прямой проход: вычисляет следующий символ с учетом символа из обучающего набора.
  • Он вычисляет потери, сравнивая предсказанный char с целевым char. (Целевой символ - это ввод, следующий за символом в наборе передачи)
  • Он вычисляет обратный проход для вычисления градиентов

Эта функция принимает в качестве входных данных:

  • список входных символов
  • список целевых символов
  • и предыдущее скрытое состояние

Эта функция выводит:

  • потеря
  • градиент для каждого параметра между слоями
  • последнее скрытое состояние

Вперед пас

Прямой проход использует параметры модели (Wxh, Whh, Why, bh, by) для вычисления следующего символа с учетом символа из обучающего набора.

xs [t] - это вектор, который кодирует символ в позиции t. ps [t] - это вероятности для следующего символа

hs[t] = np.tanh(np.dot(Wxh, xs[t]) + np.dot(Whh, hs[t-1]) + bh) # hidden state
ys[t] = np.dot(Why, hs[t]) + by # unnormalized log probabilities for next chars
ps[t] = np.exp(ys[t]) / np.sum(np.exp(ys[t])) # probabilities for next chars

или грязный псевдокод для каждого символа

hs = input*Wxh + last_value_of_hidden_state*Whh + bh
ys = hs*Why + by
ps = normalized(ys)

Обратный проход

Наивный способ рассчитать все градиенты - это пересчитать потери для небольших вариаций для каждого параметра. Это возможно, но потребует много времени. Существует методика расчета всех градиентов для всех параметров одновременно: распространение фона.
Градиенты рассчитываются в обратном порядке прямого прохода с использованием простых методов.

цель состоит в том, чтобы рассчитать градиенты для прямой формулы:

hs = input*Wxh + last_value_of_hidden_state*Whh + bh  
ys = hs*Why + by

Потеря одной точки данных

Каким образом вычисленные оценки внутри f должны изменяться t, чтобы уменьшить потери? Чтобы понять это, нам нужно получить градиент.

Поскольку все единицы вывода вносят вклад в ошибку каждой скрытой единицы, мы суммируем все градиенты, вычисленные на каждом временном шаге в последовательности, и используем это для обновления параметров. Таким образом, наши градиенты параметров становятся:

Наш первый градиент нашей потери. Мы будем распространять это через цепное правило

Цепное правило - это метод нахождения производной составных функций или функций, созданных путем объединения одной или нескольких функций.

In [14]:

def lossFun(inputs, targets, hprev):
  """                                                                                                                                                                                         
  inputs,targets are both list of integers.                                                                                                                                                   
  hprev is Hx1 array of initial hidden state                                                                                                                                                  
  returns the loss, gradients on model parameters, and last hidden state                                                                                                                      
  """
  #store our inputs, hidden states, outputs, and probability values
  xs, hs, ys, ps, = {}, {}, {}, {} #Empty dicts
    # Each of these are going to be SEQ_LENGTH(Here 25) long dicts i.e. 1 vector per time(seq) step
    # xs will store 1 hot encoded input characters for each of 25 time steps (26, 25 times)
    # hs will store hidden state outputs for 25 time steps (100, 25 times)) plus a -1 indexed initial state
    # to calculate the hidden state at t = 0
    # ys will store targets i.e. expected outputs for 25 times (26, 25 times), unnormalized probabs
    # ps will take the ys and convert them to normalized probab for chars
    # We could have used lists BUT we need an entry with -1 to calc the 0th hidden layer
    # -1 as  a list index would wrap around to the final element
  xs, hs, ys, ps = {}, {}, {}, {}
  #init with previous hidden state
    # Using "=" would create a reference, this creates a whole separate copy
    # We don't want hs[-1] to automatically change if hprev is changed
  hs[-1] = np.copy(hprev)
  #init loss as 0
  loss = 0
  # forward pass                                                                                                                                                                              
  for t in xrange(len(inputs)):
    xs[t] = np.zeros((vocab_size,1)) # encode in 1-of-k representation (we place a 0 vector as the t-th input)                                                                                                                     
    xs[t][inputs[t]] = 1 # Inside that t-th input we use the integer in "inputs" list to  set the correct
    hs[t] = np.tanh(np.dot(Wxh, xs[t]) + np.dot(Whh, hs[t-1]) + bh) # hidden state                                                                                                            
    ys[t] = np.dot(Why, hs[t]) + by # unnormalized log probabilities for next chars                                                                                                           
    ps[t] = np.exp(ys[t]) / np.sum(np.exp(ys[t])) # probabilities for next chars                                                                                                              
    loss += -np.log(ps[t][targets[t],0]) # softmax (cross-entropy loss)                                                                                                                       
  # backward pass: compute gradients going backwards    
  #initalize vectors for gradient values for each set of weights 
  dWxh, dWhh, dWhy = np.zeros_like(Wxh), np.zeros_like(Whh), np.zeros_like(Why)
  dbh, dby = np.zeros_like(bh), np.zeros_like(by)
  dhnext = np.zeros_like(hs[0])
  for t in reversed(xrange(len(inputs))):
    #output probabilities
    dy = np.copy(ps[t])
    #derive our first gradient
    dy[targets[t]] -= 1 # backprop into y  
    #compute output gradient -  output times hidden states transpose
    #When we apply the transpose weight matrix,  
    #we can think intuitively of this as moving the error backward
    #through the network, giving us some sort of measure of the error 
    #at the output of the lth layer. 
    #output gradient
    dWhy += np.dot(dy, hs[t].T)
    #derivative of output bias
    dby += dy
    #backpropagate!
    dh = np.dot(Why.T, dy) + dhnext # backprop into h                                                                                                                                         
    dhraw = (1 - hs[t] * hs[t]) * dh # backprop through tanh nonlinearity                                                                                                                     
    dbh += dhraw #derivative of hidden bias
    dWxh += np.dot(dhraw, xs[t].T) #derivative of input to hidden layer weight
    dWhh += np.dot(dhraw, hs[t-1].T) #derivative of hidden layer to hidden layer weight
    dhnext = np.dot(Whh.T, dhraw) 
  for dparam in [dWxh, dWhh, dWhy, dbh, dby]:
    np.clip(dparam, -5, 5, out=dparam) # clip to mitigate exploding gradients                                                                                                                 
  return loss, dWxh, dWhh, dWhy, dbh, dby, hs[len(inputs)-1]

Создайте предложение из модели

In [17]:

#prediction, one full forward pass
def sample(h, seed_ix, n):
  """                                                                                                                                                                                         
  sample a sequence of integers from the model                                                                                                                                                
  h is memory state, seed_ix is seed letter for first time step   
  n is how many characters to predict
  """
  #create vector
  x = np.zeros((vocab_size, 1))
  #customize it for our seed char
  x[seed_ix] = 1
  #list to store generated chars
  ixes = []
  #for as many characters as we want to generate
  for t in xrange(n):
    #a hidden state at a given time step is a function 
    #of the input at the same time step modified by a weight matrix 
    #added to the hidden state of the previous time step 
    #multiplied by its own hidden state to hidden state matrix.
    h = np.tanh(np.dot(Wxh, x) + np.dot(Whh, h) + bh)
    #compute output (unnormalised)
    y = np.dot(Why, h) + by
    ## probabilities for next chars
    p = np.exp(y) / np.sum(np.exp(y))
    #pick one with the highest probability 
    ix = np.random.choice(range(vocab_size), p=p.ravel())
    #create a vector
    x = np.zeros((vocab_size, 1))
    #customize it for the predicted char
    x[ix] = 1
    #add it to the list
    ixes.append(ix)
  txt = ''.join(ix_to_char[ix] for ix in ixes)
  print '----\n %s \n----' % (txt, )
hprev = np.zeros((hidden_size,1)) # reset RNN memory  
#predict the 200 next characters given 'a'
sample(hprev,char_to_ix['a'],200)
----
 HD')JsuLNgDw!4ejckLaA6zAt*(d'�5O;p5DoglJ!u-RN'v/:XaByA1Q"BWcO*Tip:AO/O%Wl/o)�Q1(DC.�3ztLPh/9RJ' 
?W"p
hpXoCIQgN3!j0-@49z9Hit5Kc$mn'L8
:T.T;2.bKd(GS$7 ID8@?iitb2"OSubD7wJyh3@(:5hEmKX4T?i;;Ceq,BmY2yoPHx 
----

Обучение

Эта последняя часть кода является основным циклом обучения:

  • Подайте в сеть часть файла. Размер блока seq_lengh
  • Используйте функцию потерь, чтобы:
  • Выполните прямой проход, чтобы вычислить все параметры модели для заданных пар ввода / вывода
  • Сделайте обратный проход, чтобы вычислить все градиенты
  • Распечатайте предложение из случайного числа, используя параметры сети
  • Обновите модель, используя технику адаптивного градиента Adagrad

Наполните функцию потерь входными данными и целями

Мы создаем два массива char из файла данных, один целевой сдвигается по сравнению с входным.

Для каждого символа во входном массиве целевой массив дает следующий символ.

In [15]:

p=0  
inputs = [char_to_ix[ch] for ch in data[p:p+seq_length]]
print "inputs", inputs
targets = [char_to_ix[ch] for ch in data[p+1:p+seq_length+1]]
print "targets", targets
inputs [43, 69, 58, 4, 66, 68, 73, 69, 62, 69, 60, 13, 4, 76, 63, 58, 69, 4, 35, 73, 58, 60, 68, 73, 4]
targets [69, 58, 4, 66, 68, 73, 69, 62, 69, 60, 13, 4, 76, 63, 58, 69, 4, 35, 73, 58, 60, 68, 73, 4, 47]

Adagrad для обновления параметров

Это тип стратегии градиентного спуска.

размер шага = скорость обучения

Самый простой способ обновить параметры модели:

param += dparam * step_size

Adagrad - более эффективный метод, в котором step_size становится меньше во время обучения.

Он использует переменную памяти, которая со временем увеличивается:

mem += dparam * dparam

и используйте его для вычисления step_size:

step_size = 1./np.sqrt(mem + 1e-8)

Суммируя:

mem += dparam * dparam
param += -learning_rate * dparam / np.sqrt(mem + 1e-8) # adagrad update

Smooth_loss

Smooth_loss не играет никакой роли в обучении. Это просто версия потери, отфильтрованная нижними частотами:

smooth_loss = smooth_loss * 0.999 + loss * 0.001

Это способ усреднить потери за последние итерации, чтобы лучше отслеживать прогресс.

Итак, наконец

Вот код основного цикла, который время от времени выполняет обучение и генерирует текст:

In [18]:

n, p = 0, 0
mWxh, mWhh, mWhy = np.zeros_like(Wxh), np.zeros_like(Whh), np.zeros_like(Why)
mbh, mby = np.zeros_like(bh), np.zeros_like(by) # memory variables for Adagrad                                                                                                                
smooth_loss = -np.log(1.0/vocab_size)*seq_length # loss at iteration 0                                                                                                                        
while n<=1000*100:
  # prepare inputs (we're sweeping from left to right in steps seq_length long)
  # check "How to feed the loss function to see how this part works
  if p+seq_length+1 >= len(data) or n == 0:
    hprev = np.zeros((hidden_size,1)) # reset RNN memory                                                                                                                                      
    p = 0 # go from start of data                                                                                                                                                             
  inputs = [char_to_ix[ch] for ch in data[p:p+seq_length]]
  targets = [char_to_ix[ch] for ch in data[p+1:p+seq_length+1]]
  # forward seq_length characters through the net and fetch gradient                                                                                                                          
  loss, dWxh, dWhh, dWhy, dbh, dby, hprev = lossFun(inputs, targets, hprev)
  smooth_loss = smooth_loss * 0.999 + loss * 0.001
  # sample from the model now and then                                                                                                                                                        
  if n % 1000 == 0:
    print 'iter %d, loss: %f' % (n, smooth_loss) # print progress
    sample(hprev, inputs[0], 200)
  # perform parameter update with Adagrad                                                                                                                                                     
  for param, dparam, mem in zip([Wxh, Whh, Why, bh, by],
                                [dWxh, dWhh, dWhy, dbh, dby],
                                [mWxh, mWhh, mWhy, mbh, mby]):
    mem += dparam * dparam
    param += -learning_rate * dparam / np.sqrt(mem + 1e-8) # adagrad update                                                                                                                   
  p += seq_length # move data pointer                                                                                                                                                         
  n += 1 # iteration counter
iter 0, loss: 109.861223
----
 /gQv8H'-656q@7o 0A
r2,GWqf:
l1
dPSqT18X!7g"*,M�-Gw�rM9e(M(KLW)Yt;C?3N*jWJx@i*BMdoU4K5MoeJOI/�4�-l
MA.*)HgUd,o4bW;'DK/')NE
$:z9b6xkaqA$PnVRTjRLtG�Cf gbv�DH�:os;ByVL$F(fxsSo(v86W.kt,8i miEOr6"y0o(5Mx �/ 
----
iter 1000, loss: 86.766971
----
 hi k cehi. kposod w pit se oc hebint gi d bis ,he nn ne to- t mir ildtec- aovi s tof lica . tha bilt Ig mclinlf, t orir!ee peld wafrecathe fm doathioame mhass fd  al  w, eagoy s woyigs miievonr, iee W 
----
iter 2000, loss: 69.478687
----
 he ate leth hebuelyhe wGthremilkel hore cke inse mo highe  Is hodont mlathem wise ceuG here le sime socleelldk nuSind d aS there'cecichind hither whe angave he ut soure herle tathes be nos, athlle sos 
----
iter 3000, loss: 60.740861
----
 ld oulile hisisced abdan shimttey ir ad hay leri gousse way ynas,rs simos himonac the way in ag lnere wouis sfat wad boon ooutilit; whare forey ruro ud tuuly he furny arghly lus bpers;nupdey hered bom 
----
iter 4000, loss: 56.398800
----
 her thonilgme heprailytinwok hle thit tootwis acks in aas fom songain towith waen him the waninty on the beinl win thitghed ning wspa nhat tweaw. bus hire moror'od hre in ang whithenghaw whoraliwiit b 
----
iter 5000, loss: 61.150802
----
 erinfpmeacho cuthath7rPUiitey tor Glfer lewd entin7 bo asche toOinLlen Groa ciwinreIed yoin
atho1le p1sthMyin clqot 1kee  athmtina7froit acros.in kertho inm, at7iveeiGpBoelem mo erwor ast.ot oach mche 
----
iter 6000, loss: 62.854070
----
 asidyade sy uld Eafere whey cist om not cad hay cally' robd ffot sa bustepcomed. Beger chawgesmey coull thouns,e wouls ir co thomered it hit 1o rad Inat dof hit nf, are bl oo hew of woundall c0earacle 
----
iter 7000, loss: 57.474113
----
 ems bound ht hacteld has ar teis the his oume co Boom hinde piud tor, sis  a ding nod ut, saprisdi ang
es oyoustacullaghs n6 fet havat thof was waabs angimy an atC ace rumtome thovi hef wad fafattenin 
----
iter 8000, loss: 53.622344
----
 aed the nised wat sthed anr the woulch not sued On in the eat qurecantt avem shipke faed il reln t, at have the hime hlecr hid coobd, beghem aly en andand sidf and lers ceeve ild on in ad Gred  oipnea 
----
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
<ipython-input-18-800feb8589cf> in <module>()
     13 
     14   # forward seq_length characters through the net and fetch gradient
---> 15   loss, dWxh, dWhh, dWhy, dbh, dby, hprev = lossFun(inputs, targets, hprev)
     16   smooth_loss = smooth_loss * 0.999 + loss * 0.001
     17 
<ipython-input-14-0bac30c55025> in lossFun(inputs, targets, hprev)
     28     xs[t][inputs[t]] = 1 # Inside that t-th input we use the integer in "inputs" list to  set the correct
     29     hs[t] = np.tanh(np.dot(Wxh, xs[t]) + np.dot(Whh, hs[t-1]) + bh) # hidden state
---> 30     ys[t] = np.dot(Why, hs[t]) + by # unnormalized log probabilities for next chars
     31     ps[t] = np.exp(ys[t]) / np.sum(np.exp(ys[t])) # probabilities for next chars
     32     loss += -np.log(ps[t][targets[t],0]) # softmax (cross-entropy loss)
KeyboardInterrupt:

Заключительные слова:

Следуйте за мной, когда я пишу о машинном обучении, науке о данных и блокчейне. Вы можете следить за мной и моим кодом на Github

Хорошего дня !!!