Изначально, мысли о «скрытом коде» меня посетили где-то с месяц назад. В этом посте я опишу предпосылки понятия.
Немного теории алгоритмов
Есть такая Машина Тьюринга, абстрактная вычислительная машина, представляющая собой (в оригинале) бесконечную ленту и некоторое устройство, способное двигаться по ней. По заданной программе, оно может или двигаться по ленте влево-вправо, или считывать-записывать символы конечного алфавита в ячейку ленты.
Казалось бы, что за чудесное устройство — в наши-то времена. Если бы не тезис Черча, то может быть всё было не так интересно.
Любой интуитивно вычислимый алгоритм реализуем на машине Тьюринга.
Есть еще утверждения, что физически реализуемый алгоритм, на ней же и реализуется.
Доказательств нет. Доказать, возможно, и невозможно, но поискать свидетельства — достаточно универсальные — весьма интересно.
Рекуррентные нейронные сети
Нейронные сети сами по себе — это слои элементарных вычислителей, по сути сеть из линейных моделей вида y = kx + b (где x может быть вектором любой размерности), к каждой из которой применили некоторое нелинейное преобразование. Чаще всего в настоящее время — это y = max(0, x).
Рекуррентные нейросети отличаются тем, что на входе у них не просто вектора, а вектора с историей, и в блоках сети есть аналоги памяти.
Что вдруг про них? А то что они Тьюринг-полные, то есть эквивалентны машинам Тьюринга (последние изобрели в 1936, а через 60 лет установили этот факт).
Recurrent neural networks are theoretically Turing complete and can run arbitrary programs to process arbitrary sequences of inputs.
Это уже английская википедия.
Прореживание
Есть в нейросетях такая вещь как прореживание (dropout). По сути, это выкидывание случайным образом части вычислений из сети в процессе обучения (о котором сейчас неинтересно). Интересно то, что прореживание можно оставлять и при выводе (прогнозе) сетью.
Вообще, раз выкидывание случайно — то и результат случаен. Но когда этих результатов много, их усреднение даёт сам прогноз. Формального доказательства этого факта я не нашел (не искал), но поставил «эксперимент» для простой нейросети (и много раз делал подобное — в практике уже с другими).
class RNN(nn.Module):
def __init__(self, outputs=1, channels=1, dropout=0.2):
super(RNN, self).__init__()
self.gru = nn.GRU(
input_size=channels,
hidden_size=128,
dropout=dropout,
batch_first=True
)
self.drop = nn.Dropout(dropout)
self.output = nn.Linear(128, outputs)
def forward(self, X):
X = self.gru(X)[0][:, -1]
X = self.drop(X)
X = self.output(X)
return X
В качестве данных выбрал простую формулу,
$$ sin^2(x) + \frac {cos(x)} {2} + \xi, \: \xi \sim N(0, 0.1) $$
Распределение истинных и прогнозных значений, а также сравнение самого истинного и прогнозного для (последнего значения из 50 для прогнозируемой серии) — всё как на картинке.
Так суть в чем… в том что если прореживание не выключать, то для одного случая прогноза, мы можем получить целую кучу разных.
И видно, что красную — прогноз без dropout — можно сравнивать как с оригинальной величиной, так и со средним по прореженным. Черным здесь 100 случайных значений прогноза (на все те же 50 точек вперед), полученные с включенным dropout.
Основная версия
Это меня натолкнуло на мысль, что при «выводе» (он же inference, он же прогноз), имеется где-то в глубине программа (машины Тьюринга?), состоящая из элементарных сюжетов, схлапывающихся в итоговое прогнозное. Фильтрующееся, или агрегирующее, тут не суть.
Поиск свидетельств
Дальше всё планируется, что будет разворачиваться вокруг этой концепции. Анонсируя следующий материал, могу дать ссылку на код.
Но смотреть его далее вышеприведенных картинок не рекомендую, ничего понятно не будет 🙂
Это, конечно, всё идея. Хотелось бы её развить.
4 комментария на «“Фильтры базы сюжетов”»
Ничего не понял, но очень интересно.
Где мутновато, если б знать, там мог бы и поподробнее 😉
Общая идея понятна, но вот то над чем был сделан вывод совсем нет, так как статья рассчитана, что читатель поймёт данные и будет иметь опыт прореживаний. А хочется по рассуждать )))))
Данные — это просто «испорченная» синусоида, которая прогнозируется своей историей. Прореживание — это когда в A* 1 + B * 2 + C * 3 выкидывают например +2 путем выставления B = 0. Случайно, а и таких случайно — много раз.
Для нейросеток наблюдается вот такое поведение — что прогноз это среднее.