В этом посте я хочу поговорить о закономерностях, которые могут находить нейронные сети.
Многие руководства для начинающих фокусируются на технике написания кода для нейронных сетей, а вопросы «логики» (что могут нейронные сети? какие архитектуры лучше всего подходят для каких задач и почему?) часто остаются в стороне.
Надеюсь, мой пост поможет новичкам лучше понять возможности нейронных сетей.
Для этого мы попробуем посмотреть, как они справляются с некоторыми модельными задачами.
Примеры кода будут предоставлены на Python с использованием библиотеки keras. Задание 1. Начнем с чего-то простого.
Давайте построим нейронную сеть, аппроксимирующую синус.
Получаем следующий график:import numpy as np import matplotlib import matplotlib.pyplot as plt from keras.models import Sequential from keras.layers import Dense def get_X_y(n): X = np.random.uniform(0, np.pi, n) y = np.sin(X) return X, y n = 40 X, y = get_X_y(n) print("X shape:", X.shape) model = Sequential() model.add(Dense(6, input_dim=1, activation='relu')) model.add(Dense(4, activation='relu')) model.add(Dense(1, activation='sigmoid')) model.compile(loss='mean_squared_error', optimizer='adam', metrics=['mean_squared_error']) model.fit(X, y, epochs=1000, batch_size=4) X_test = np.linspace(start=0, stop=np.pi, num=500) print("X test shape:", X_test.shape) y_test = model.predict(X_test) font = {'weight': 'bold', 'size': 25} matplotlib.rc('font', **font) axes = plt.gca() axes.set_ylim(0, 1) plt.plot(X_test, y_test, c='green', marker='o', markersize=5) plt.title("Sinus approximated by neural network") plt.yticks(np.arange(0, 1, 0.1)) plt.grid() plt.show()
Как мы видим, нейросеть успешно справилась с задачей аппроксимации простой функции.
Задача 2. Посмотрим, как нейросеть справится с более сложной задачей.
Мы введем значения x, равномерно распределенные на интервале [0, 1], а y зададим случайным образом: для x < 0.6, y will be a random variable taking the value 0 with probability 0.75 and 1 with probability 0.25 (that is, a binomial random variable with p=0.25).
For x > 0,6, y будет случайной величиной, принимающей значение 0 с вероятностью 0,3 и значение 1 с вероятностью 0,7. В качестве оптимизируемой функции возьмем среднеквадратическую ошибку.
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers import Dense
def get_X_y(n):
X = np.random.uniform(0, 1, n)
y0 = np.random.binomial(size=n, n=1, p=0.25)
y1 = np.random.binomial(size=n, n=1, p=0.7)
y = np.where(X < 0.6, y0, y1)
return X, y
n_inputs = 1
n_hidden1 = 100
n_hidden2 = 50
n_outputs = 1
n = 2000
X, y = get_X_y(n)
print("X shape:", X.shape)
model = Sequential()
model.add(Dense(n_hidden1, input_dim=1, activation='relu'))
model.add(Dense(n_hidden2, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy'])
model.fit(X, y, epochs=200, batch_size=100)
X_test = np.linspace(start=0, stop=1, num=100)
print("X test shape:", X_test.shape)
y_test = model.predict(X_test)
font = {'weight': 'bold',
'size': 25}
matplotlib.rc('font', **font)
axes = plt.gca()
axes.set_ylim(0, 1)
plt.plot(X_test, y_test, c='green', marker='o', markersize=5)
plt.title("Binomial distribution approximated by neural network")
plt.yticks(np.arange(0, 1, 0.1))
plt.grid()
plt.show()
Получаем следующий график аппроксимированной нейронной сетью функции:
Как мы видим, нейронная сеть аппроксимировала математическое ожидание нашей случайной величины y. Итак, нейронные сети могут (в принципе) аппроксимировать средние значения случайных величин в зависимости от параметров.
Например, мы могли бы ожидать, что они решат следующую проблему: люди с доходом менее 1000 долларов в среднем несчастливы, а люди с доходом выше 1000 долларов в среднем счастливы; нам нужно научиться прогнозировать «уровень счастья» в зависимости от дохода.
Нейросеть сможет найти зависимость среднего уровня счастья от дохода, несмотря на то, что среди людей с любым уровнем дохода есть как счастливые, так и несчастные люди.
Задача 3. Теперь перейдем к прогнозированию последовательностей.
Будем рассматривать последовательности 0 и 1, заданные следующим правилом: 10 членов с равной вероятностью будут равны 0 или 1, а одиннадцатый равен 1, если предыдущий член равен 0, и равновероятен 0 или 1, если предыдущий член равен 0 и 1. член равен 1. Мы будем генерировать такие последовательности длиной 11 (10 входных членов последовательности и один, последний, который мы предсказываем) и обучать на них нашу рекуррентную нейронную сеть.
А после обучения проверим, как он справляется с предсказанием на новых последовательностях (тоже длины 11).
import numpy as np
from keras.models import Sequential
from keras.layers import LSTM, Dense
def get_X_y(m, n):
X = np.random.binomial(size=(m,n), n=1, p=0.5)
y0 = np.ones(m)
y1 = np.random.binomial(size=m, n=1, p=0.5)
y = np.where(X[:, n-1]==0, y0, y1)
X = np.reshape(X, (X.shape[0], X.shape[1], 1))
return X, y
model = Sequential()
model.add(LSTM(units=50))
model.add(Dense(units=1))
model.compile(optimizer = 'adam', loss = 'mean_squared_error')
X_train, y_train = get_X_y(1000, 10)
model.fit(X_train, y_train, epochs = 20, batch_size = 32)
m_test = 12
n_test = 10
X_test, y_test = get_X_y(m_test, n_test)
y_predicted = model.predict(X_test)
for i in range(m_test):
print("x_last=", X_test[i, n_test-1, 0], "y_predicted=", y_predicted[i, 0])
Давайте посмотрим, какие прогнозы делает наша нейросеть на тестируемых последовательностях (ваши результаты будут другими, так как здесь случайность присутствует как в выборе последовательностей, так и в обучении нейросети).
Порядковый номер | Предпоследний член последовательности | Прогнозируемое значение |
---|---|---|
1 | 0 | 0.96 |
2 | 0 | 0.95 |
3 | 0 | 0.97 |
4 | 0 | 0.96 |
5 | 0 | 0.96 |
6 | 1 | 0.45 |
7 | 0 | 0.94 |
8 | 1 | 0.50 |
9 | 0 | 0.96 |
10 | 1 | 0.42 |
11 | 1 | 0.44 |
12 | 0 | 0.92 |
Подобный пример из «реальной жизни» мог бы выглядеть так: «если я сегодня пойду в кино, то завтра я буду обедать в ресторане; Если я сегодня пойду в театр, то завтра пообеду где угодно».
Нейронная сеть, как мы видели, может улавливать закономерности такого типа и предсказывать поход в ресторан на основе похода в кино (и предсказывать «что-то среднее» на основе похода в театр).
Задача 4. Усложним задачу нейросети.
Пусть все будет как в предыдущем примере, только одиннадцатый член последовательности будет определяться не предыдущим, а вторым членом последовательности (по тому же правилу).
Код мы здесь приводить не будем, так как он практически ничем не отличается от предыдущего.
Мой эксперимент показал, что нейронная сеть все равно находит закономерность, но за большее время (пришлось использовать для обучения 100 эпох вместо 20).
Таким образом, нейронные сети могут (в принципе еще раз уточним) ловить достаточно долговременные зависимости (в нашем «примере из жизни» — ловить шаблоны типа «Я сегодня иду в ресторан, если неделю назад я был в кино»).
»).
Задача 5. Давайте посмотрим, как нейронная сеть использует имеющуюся информацию для составления прогноза.
Для этого мы будем тренироваться на последовательностях длиной 4. Всего у нас будет 3 разные равновероятные последовательности: 0, 0, 1, 1
0, 1, 0, 1
0, 1, 1, 0
Таким образом, после исходной комбинации 0, 0 мы всегда встретим две единицы, после комбинации 0, 1 мы с равной вероятностью встретим 0 или 1, но последнее число мы будем знать наверняка.
Теперь мы попросим нашу нейронную сеть возвращать последовательности, установив return_sequences=True. В качестве предсказанных последовательностей мы возьмём собственные последовательности, сдвинутые на один шаг и дополненные справа нулем.
Теперь уже можно предположить, что произойдет: на первом шаге нейросеть выдаст число, близкое к 2/3 (так как с вероятностью 2/3 второе слагаемое равно 1), а затем для комбинации 0 , 0 выдаст два числа, близких к единице, а для 0, 1 сначала выдаст число, близкое к 0,5, а потом выдаст число, близкое к 0 или 1, в зависимости от того, получили ли мы последовательность 0, 1, 0 или 0, 1, 1. В конце нейронная сеть всегда будет выдавать число, близкое к 0. Тестирование с помощью следующего кода показывает, что наши предположения верны.
import numpy as np
from keras.models import Sequential
from keras.layers import LSTM, Dense
import random
def get_X_y(n):
X = np.zeros((n, 4))
z = np.array([random.randint(0, 2) for i in range(n)])
X[z == 0, :] = [0, 0, 1, 1]
X[z == 1, :] = [0, 1, 0, 1]
X[z == 2, :] = [0, 1, 1, 0]
y = np.zeros((n, 4))
y[:, :3] = X[:, 1:]
X = np.reshape(X, (X.shape[0], X.shape[1], 1))
y = np.reshape(y, (y.shape[0], y.shape[1], 1))
return X, y
model = Sequential()
model.add(LSTM(units=20, return_sequences=True))
model.add(Dense(units=1))
model.compile(optimizer = 'adam', loss = 'mean_squared_error')
X_train, y_train = get_X_y(1000)
model.fit(X_train, y_train, epochs = 100, batch_size = 32)
X_test = np.zeros((3, 4))
X_test[0, :] = [0, 0, 1, 1]
X_test[1, :] = [0, 1, 0, 1]
X_test[2, :] = [0, 1, 1, 0]
X_test = np.reshape(X_test, (3, 4, 1))
y_predicted = model.predict(X_test)
print(y_predicted)
Из этого примера мы видим, что нейросеть может динамически менять прогноз в зависимости от полученной информации.
Мы бы сделали то же самое, если бы пытались предсказать определенную последовательность: когда доступная информация позволяет нам оценить вероятности результатов на следующем шаге, мы делаем прогноз на основе этой информации; но когда мы узнаем дополнительную информацию на следующем шаге, мы меняем прогноз в зависимости от нее.
Итак, если мы видим, что кто-то идет к нам из темноты, мы говорим «это человек, более подробностей мы не знаем»; когда мы начинаем различать в темноте длинные волосы, мы говорим «вероятно, это женщина».
Но если затем учесть, что у человека есть усы, то мы скажем, что это, вероятно, мужчина (хотя и с длинными волосами).
Как мы видели, нейронная сеть делает то же самое, используя всю доступную на данный момент информацию для составления прогноза.
Итак, мы рассмотрели простые примеры того, как работают нейронные сети и какие закономерности они могут находить.
В целом мы увидели, что нейронные сети часто ведут себя достаточно «разумно», делая прогнозы, близкие к тем, которые сделал бы человек.
Хотя следует отметить, что для понимания простых закономерностей им нужно гораздо больше данных, чем людям.
Теги: #Машинное обучение #нейронные сети #Keras #LSTM
-
Магия Массовых Фотоманипуляций
19 Oct, 24 -
Смартфон Без Динамика
19 Oct, 24