Программист
0,0
рейтинг
26 января в 13:13

Разработка → Пирожки в дистрибутивной семантике из песочницы

Уже несколько месяцев с любопытством гляжу в сторону дистрибутивной семантики — познакомился с теорией, узнал про word2vec, нашёл соответствующую библиотеку для Питона (gensim) и даже раздобыл модель лексических векторов, сформированную по национальному корпусу русского языка. Однако для творческого погружения в материал не хватало душезабирающих данных, которые было бы интересно через дистрибутивную семантику покрутить. Одновременно с этим увлечённо почитывал стишки-пирожки (эдакий синтез задиристых частушек и глубокомысленных хокку) — некоторые даже заучивал наизусть и по случаю угощал знакомых. И вот, наконец, увлечённость и любопытство нашли друг друга, породив воодушевляющую идею в ассоциативных глубинах сознания — отчего бы не совместить приятное с полезным и не собрать из подручных средств какой-нибудь «поэтичный» поисковик по базе пирожков.
из ложных умозаключений
мы можем истину сложить
примерно как перемножают
два отрицательных числа

«Поэтичность» поиска предполагалось реализовать за счёт врождённой способности дистрибутивных векторов показывать степень семантического сходства лексем самым что ни на есть действительным числом (чем меньше угол между векторами слов, тем с большей вероятностью эти слова близки по смыслу — косинусная мера, классика жанра, в общем). Например, «принцесса» и «пастух» гораздо менее близки, чем «пастух» и «овца»: 0.139 против 0.603, что, наверное, логично — вектора национального корпуса должны отражать суровую реальность, а не сказочный мир Г.Х. Андерсена. Способ же расчёта глубины корреляции (диффузии) запроса и пирожка проявился практически сам собой (дёшево и сердито) как нормализованная сумма сходств каждого слова из списка X с каждым словом списка Y (стоп-слова выкидывались, все остальные приводились к нормальной форме, но об этом позже).

Код расчёта семантической диффузии
def semantic_similarity(bag1, bag2: list, w2v_model, unknown_coef=0.0) -> float:
    sim_sum = 0.0
    for i in range(len(bag1)):
        for j in range(len(bag2)):
            try:
                sim_sum += w2v_model.similarity(bag1[i], bag2[j])
            except Exception:
                sim_sum += unknown_coef
    return sim_sum / (len(bag1) * len(bag2))


Результаты поэтического поиска и порадовали, и позабавили. Например, на запрос «музыка» был выдан следующий poem-list:

[('оксане нравилось фламенко'
  'олегу классика и джаз'
  'они вдвоём со сцены пели'
  'про лагеря и мусоров',
  0.25434666007036322),
 ('зашлась в оргазме пианистка'
  'в тумане ноты и рояль'
  'а ей играть ещё фермату'
  'пятнадцать тактов и финал',
  0.19876923472322899),
 ('люблю тебя как шум прибоя'
  'как тёплый ветер как стихи'
  'а толика люблю как танцы'
  'как поцелуи как поспать',
  0.19102709737990775),
 ('мне снится рокот космодрома'
  'и ледяная синева'
  'но я не тычу это людям'
  'об этом песен не пою',
  0.15292901301609391),
 ('индийский танец зита гите'
  'танцует страстно у костра'
  'но не отбрасывает тени'
  'сестра',
  0.14688091047781876)]

Здесь примечательно, что слова «музыка» нет ни в одном пирожке, из занесённых в базу. Однако все пирожковые ассоциации весьма музыкальны и степень их семантической диффузии с запросом довольно высока.

Теперь по порядку о проделанной работе (исходники на GitHub).

Библиотеки и ресурсы


  • Модуль pymorphy2 — для приведения слов к нормальной грамматической форме
  • Модуль gensim — подключение word2vec модели для семантической обработки
  • Так же для работы необходима дистрибутивная модель лексических векторов ruscorpora (320 Мб)

Формирование модели данных


олег представил в виде текста
все что оксана говорит
разбил на главы и абзацы
и на отдельные слова

Первым делом из текстового файла (poems.txt), в котором содержатся стишки-пирожки (порядка восьми сотен), нарезается список, собственно, содержащий эти пирожки в виде строк. Далее из каждого строко-пирожка выжимается мешок слов (bag of words), в котором каждое слово приведено в нормальную грамматическую форму и из которого выкинуты шумовые слова. После чего для каждого мешка вычисляется семантическая «плотность» (интро-диффузия) пирожка и формируется специфический ассоциативный список (помогает понять, какой смысловой слой превалирует с точки зрения модели дистрибутивных векторов). Всё это удовольствие укладывается в словарь под соответствующие ключи и записывается в файл в формате json.

Код выжимания bag of words
def canonize_words(words: list) -> list:
    stop_words = ('быть', 'мой', 'наш', 'ваш', 'их', 'его', 'её', 'их',
                  'этот', 'тот', 'где', 'который', 'либо', 'нибудь', 'нет', 'да')
    grammars = {'NOUN': '_S',
                'VERB': '_V', 'INFN': '_V', 'GRND': '_V', 'PRTF': '_V', 'PRTS': '_V',
                'ADJF': '_A', 'ADJS': '_A',
                'ADVB': '_ADV',
                'PRED': '_PRAEDIC'}

    morph = pymorphy2.MorphAnalyzer()
    normalized = []
    for i in words:
        forms = morph.parse(i)
        try:
            form = max(forms, key=lambda x: (x.score, x.methods_stack[0][2]))
        except Exception:
            form = forms[0]
            print(form)
        if not (form.tag.POS in ['PREP', 'CONJ', 'PRCL', 'NPRO', 'NUMR']
                or 'Name' in form.tag
                or 'UNKN' in form.tag
                or form.normal_form in stop_words):  # 'ADJF'
            normalized.append(form.normal_form + grammars.get(form.tag.POS, ''))
    return normalized


Код формирования модели данных
def make_data_model(file_name: str) -> dict:
    poems = read_poems(file_name)
    bags, voc = make_bags(poems)
    w2v_model = sem.load_w2v_model(sem.WORD2VEC_MODEL_FILE)
    sd = [sem.semantic_density(bag, w2v_model, unknown_coef=-0.001) for bag in bags]
    sa = [sem.semantic_association(bag, w2v_model) for bag in bags]
    rates = [0.0 for _ in range(len(poems))]
    return {'poems'       : poems,
            'bags'        : bags,
            'vocabulary'  : voc,
            'density'     : sd,
            'associations': sa,
            'rates'       : rates}


Общий анализ модели


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

Плотность, выжимка, ассоциативный список
 0.16305980883482543
['убить_V', 'обида_S', 'гнев_S', 'похоть_S', 'гордыня_S', 'зависть_S', 'тоска_S', 'остаться_V', 'милосердие_S', 'добить_V']
['жалость_S', 'ненависть_S', 'злоба_S', 'ревность_S', 'страх_S', 'страсть_S', 'злость_S', 'стыд_S', 'печаль_S', 'презрение_S']


Ожидаемо в топ «твёрдых» попали пирожки, в которых наличествует много близких по смыслу слов — как синонимичных и так антонимичных (причём нечётко) и без труда обобщаемых в какую-нибудь категорию (в данном случае — это эмоции).

Самый «мягкий» пирожок:
на этом судне мы спасёмся
не будь я прародитель ной
поставьте судно не дурачьтесь
больной

Плотность, выжимка, ассоциативный список
 -0.023802562235525036
['судно_S', 'спастись_V', 'прародитель_S', 'поставить_V', 'дурачиться_V', 'больной_A']
['корабль_S', 'заболевать_V', 'парусник_S', 'больной_S', 'заболеть_V', 'теплоход_S', 'бригантина_S', 'лодка_S', 'припадочный_S', 'бот_S']


Здесь отрицательная плотность, как мне кажется, во многом обусловлена тем, что в ассоциативный список не попал больничный смысл слова «судно». Это вообще одно из слабых мест дистрибутивно-семантических моделей — в них, как правило, одно значение лексемы подавляет популярностью все остальные.

Поисковые запросы по модели


О том как работает поиск, в сущности, было написано выше — пирожки беззатейливо сортируются по уровню их диффузии (обобщённого семантического сходства) со словами запроса.

Код
def similar_poems_idx(poem: str, poem_model, w2v_model, topn=5) -> list:
    poem_bag = dm.canonize_words(poem.split())
    similars = [(i, sem.semantic_similarity(poem_bag, bag, w2v_model))
                for i, bag in enumerate(poem_model['bags'])]
    similars.sort(key=lambda x: x[1], reverse=True)
    return similars[:topn]


Несколько примеров:

Сознание
>> pprint(similar_poems("сознание", pm, w2v, topn=5))
[('олег пытается не думать'
  'но мысли проникают в мозг'
  'скорей всего тому виною'
  'негерметичность головы',
  0.13678271365987432),
 ('моё прекрасно настроенье'
  'красивы тело и лицо'
  'лишь мысли грязные немного'
  'но что поделаешь весна',
  0.1337333519127788),
 ('по логике общаться с зомби'
  'весьма полезней чем с людьми'
  'для них мозги имеют ценность'
  'и важно что у вас внутри',
  0.12728715072640368),
 ('землянин где твоя землянка'
  'не в смысле выемка в земле'
  'а человек с твоей планеты'
  'и выемка внутри него',
  0.12420312280907075),
 ('вы ничего сказала ольга'
  'вы очень даже ничего'
  'ничтожество пустое место'
  'знак ноль на ткани бытия',
  0.11909834879893783)]


Свобода воли
>> pprint(similar_poems("свобода воли", pm, w2v, topn=5))
[('андрей любил немного выпить'
  'а много выпить не любил'
  'но заставлял себя надраться'
  'железной воли человек',
  0.12186796715891397),
 ('убей обиду гнев и похоть'
  'гордыню зависть и тоску'
  'а то что от тебя осталось'
  'из милосердия добей',
  0.10667187095852899),
 ('забудьте слово секс геннадий'
  'у нас в стране не принят секс'
  'у нас альтернатива сексу'
  'у нас любовь и доброта',
  0.10161426827828646),
 ('приятно быть кому то музой'
  'и знать что если бы не ты'
  'его бы творческому дару'
  'кранты',
  0.10136245188273822),
 ('я шла и на меня напали'
  'отняли всё но не смогли'
  'отнять любовь к земле и к людям'
  'и веру в мир и доброту',
  0.098855948557813059)]


Зима
>> pprint(similar_poems("зима", pm, w2v, topn=5))
[('зимой дороги убирают'
  'под грязный снег и гололед'
  'ну а когда зима минует'
  'дороги снова достают',
  0.1875936291758869),
 ('идет безногий анатолий'
  'стоп как же он идет без ног'
  'а так как снег идет как осень'
  'идет за летом в сентябре',
  0.18548772093805863),
 ('илья готовил сани летом'
  'телегу ладил он зимой'
  'так и возился постоянно'
  'кататься он не успевал',
  0.16475609244668787),
 ('захарий смотрит исподлобья'
  'на проходящую весну'
  'на девок бегающих в поле'
  'на трактор тонущий в реке',
  0.14671085483137575),
 ('я не хочу как все в могилу'
  'и в крематорий не хочу'
  'хочу быть скормленным весною'
  'грачу',
  0.13253569027346904)]


Очевидно, что поиск сквозь призму других дистрибутивно-семантических моделей (различные корпуса, алгоритмы обучения, размерности векторов) будет давать другие результаты. В целом технология работает, и работает весьма удовлетворительно. Нечёткий смысловой поиск реализуется легко и беззаботно (по крайней мере, на относительно небольшом объёме данных). В дальнейшем, если дойдут руки и, самое главное, догонит голова, планирую реализовать оценку рейтинга пирожков на основе обучающей выборки. Для начала — простой взвешенной суммой (в роли весового коэффициента будет выступать семантическая диффузия). Потом, возможно, пригодится что-нибудь из machine learning.
@drafterleo
карма
22,0
рейтинг 0,0
Программист
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (41)

  • +3
    Черт, вот на чем надо тренировать эти ваши рекуррентные сети. К черту Шекспира, нам нужен генератор пирожков! Не поделитесь, откуда выборку брали и можно ли достать еще?

    По теме — выглядит круто, никогда не занимался текстом, но word2vec издалека выглядел очень интересной штукой. Дилетантский вопрос — а сделать условный шаг дальше и семантически сравнивать предложения/фразы кто-нибудь же наверняка пробовал, да?
    • +3
      Пирожки (и порошки :)) надёргал в интернете, сколько было не лень. Даже пришлось небольшой скриптик выдумывть, чтобы отсеять повторы. Честно говоря, сам был бы рад найти увесистый сборник одним файлом, но не нашёл.

      Обрабатывать фразы word2vec, конечно же, уже пробовали (всё украдено до нас :)) — просто сливали несколько слов в одну лексему, а потом всё то же самое. В английском это проще, в русском сложней — у нас, в виду синтетичности языка, многие слова сами по себе уже маленькие предложения, отчего грамматическая нормализация вносит гораздо больше смысловых искажений.
    • +2
      На всякий случай — вот сайт с целой кучей пирожков perashki.ru
    • +1
      Обучил lstm Карпатого на github.com/drafterleo/pie-poem/blob/master/poems.txt. Гласные и строчки считать более-менее научилось, слова — примерно, согласования никакого.

      я был живёшь веселою клей
      я тронангию истязный
      чем банков можно сементами
      стрелы не знала и назвать

      прохожих как внором из солнцев
      возьмите на девять силят
      я надо открываю главку
      и сразу сершия с небюс
      • 0
        Черт, вы меня опередили) Сколько слоев/нейронов? Я пару ночей гонял два по 512, получается примерно такая же фигня:

        мы все умер и под другой
        тога значит режет стены
        в водьше наступили к куру
        труда не выновить в культор

        кричит олег а под летом
        воя с насон присопяты
        закончится веси беспорность
        а теля понячный продкайся

        с Шекспиром у Карпатого как-то лучше получалось, так что я теперь пробую три слоя)
        • 0
          2 слоя, 128 нейронов
        • 0
          Нейросеть :)
          >>  pprint(ap.similar_poems("нейросеть", pm, w2v, topn=5))
          [('малошумящий усилитель'
            'для усиления шумов'
            'производимых аппаратом'
            'для шумоподавления',
            0.12743493124366839),
           ('лилит не женщина а просто'
            'эфир лилейной кислоты'
            'по аналогии с боратом'
            'который вовсе не казах',
            0.11525529312273997),
           ('шум квантования пространства'
            'в диапазоне микроволн'
            'наш мир дискретный отличает'
            'от теплых ламповых миров',
            0.10532414661844355),
           ('теоретически я умер'
            'осталось только подогнать'
            'ряд главных функций организма'
            'под этот жесткий постулат',
            0.10308405684535353),
           ('налаживаю генератор'
            'и добиваюсь чтобы ток'
            'был строго синусоидален'
            'как наши встречи с зульфиёй',
            0.10109047862104875)]
          



          Зарядить нейросеть в качестве генератора — классная идея, конечно. Хотя результаты (на данном этапе) выглядят жутковато. Смотришь и начинаешь постигать природу шизофрении. Кстати, а как эти штуки показывают себя на абстрактных грамматиках? Быстро раскалывают алгоритм?
          • 0
            Я настолько никогда не занимался текстом, что даже не знаю, что это такое) Плохие результаты на текущем этапе, по крайней мере у меня, кажется, объясняются для начала тем, что я скармливаю сети слишком маленький кусок данных для предсказания следующей буквы (нужно по куску из 20 букв предсказать 21-ю). По той же ссылке на Карпатого у него сотня букв — попробую теперь так)

            Насколько я понимаю, на пальцах это должно работать примерно так — сеть должна держать в памяти такое число знаков, чтобы в него помещалась структура, которую мы хотим воспроизвести. Если говорить только о рифме, то получается, что нужно помнить последние две строки, скажем. Если о смысле — то четыре, и тут мне уже просто интересно, насколько это вообще реально — воспроизвести осмысленные (согласованные) четыре строки подряд.
            • 0
              Только она держит не сами знаки, а какую-то метаинформацию о них (см. картинки).

              Я бы предположил, что проблема еще и в малом размере обучающей выборки (Шекспира было в полтора раза больше).
              • 0
                Там ниже в комментах привезли еще — вместе получается 1.4 мегабайта примерно.
                • 0
                  1.4 в UTF8. Т.е. полезного почти в 2 раза меньше.
                • 0
                  леча на резу ладонотки
                  взяли рыбаки из клады
                  друг все со рут огонь негромко
                  сведляна сердце пропагал

                  с конечно вечером меняешь
                  а у косу свою цену
                  елена мне мы пять восьмого
                  и больше не хочу подходь

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

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


                  256 нейронов, 2 слоя, 3.3мб обучающая выборка
            • 0
              Абстрактные грамматики — штука в общем-то простая. По сути, вероятностный генератор (алгоритм) последовательностей символов на марковской цепи (несколько лет назад делал по этой теме программку, правда с уклоном в людей, а не в нейросети :)). Последовательности, сгенерированные разными алгоритмами, классифицируются на раз (через n-граммы или наивным байесом), а вот реконструировать алгоритм по последовательности (т.е. построить изоморфный генератор) — задача куда менее тривиальная. Судя по тому, что я вижу (эксперименты с шекспиром и пирожками), рекуррентные сети должны щёлкать абстрактные грамматики как семечки. По идее — школьная задачка в этой сфере (ведь можно легко проверить результат, посчитать степень корреляции генерируемых последовательностей). Но в сети ничего не нашёл (впрочем, искал не очень глубоко :)). Быть может, вам что-нибудь попадалось об этом?
              • 0
                О, спасибо за ликбез) Быстрый гуглинг выдал вот такую штуку.
                • 0
                  Да, это оно. Взаимное спасибо. Правда, там, насколько я разобрался, основной упор делается на распознавание грамматики, а не на генерацию «фальшивых» (в хорошем смысле этого слова :)) последовательностей. Хотя, если рекуррентная сеть может узнавать, то она, видимо, способна и продуцировать «подделки» малоотличимые от оригинала. Так?
  • +2
    Ещё стоило бы отметить, что дистрибутивная семантика является одним из краегольных камней алгоритмов глубокого обучения (и вообще NN и многих вероятностных моделей), поэтому очень полезно и важно с ней разобраться :-)

    Подробнее можно посмотреть в видео-лекциях школы по глубокому обучению вот тут и ещё можно глянуть крутой курс от Udacity вот тут.
  • +4
    В результаты среди пирожков затесались порошки.
    • +1
      Насколько я смог уловить поэтику, «порошок» это искажённое произнесение «пирожка» — вроде как по смыслу то же самое, а по форме немного другое :).
      • +2
        Не совсем так. Пирожок — 9-8-9-8, ямб без рифмы, порошок или порох — 9-8-9-2, с рифмой 2-4, если память не изменяет. Исторически порошки появились из пирожков, но стали вполне себе самостоятельным форматом.
        Есть еще другие похожие формы. Самая распространенная — двустрочная, например:
        зачем учить нас как работать
        вы научитесь как платить
        © bazzlan
        • +1
          Вот видите как замечательно, я в порошке увидел озорного сынишку пирожка, а вы узрели воспламеняющий порох. Поэзия однако — стихия субъективной глубины :). В целом, соглашусь, порошки за счёт (неожиданной, как правило) рифмовки «отжигают» подинамичней пирожков. На мой взгляд, если хороший пирожок что-то в душе разминирует, то хороший порошок наоборот — подрывает. Вот мой любимый (и кажется в тему :))
          лишает сна срывает крышу
          и переводит речь на мат
          незапихуемость идей
          в формат

          © ракша
          • +1
            я в порошке увидел озорного сынишку пирожка, а вы узрели воспламеняющий порох.


            хм, а мне тут виделась отсылка к мему «порошок уходи» :)
      • +2
        Вообще, пирожки можно печь на лету, если внутренний голос на ритм настроить. Плохие, но формально — пирожки.
        Настолько просто это делать
        что я в полуночном бреду
        решил скостылить быстро скриптик
        и всех поэтов заменить

        И вообще да, надо в эту сторону подумать. А вы могли бы прислать ваш корпус пирожков для таких целей?
        • +1
          В посте есть ссылка. Я тоже прямо заинтересовался)
        • +1
          С этими пирожками — главное не объестся. Я вот, чувствую, за последнюю неделю переел. Но всё же, если, вдруг, пополните корпус пирожков — надеюсь на ссылку алаверды :).
  • +1
    Да это же шикарно!!! как только появится свободное время, реализуются подобное у себя на машине и улучшу базу пирожков ^_^
  • +1
    Очень интересно, спасибо! А по теории что почитать рекомендуете?
    • +1
      Откровенно говоря, затрудняюсь ответить, ибо не являюсь большим специалистом в этой области. Если что-то обзорное по дистрибутивной семантике — есть неплохая лекция Андрея Кутузова. Если поразбираться, что под капотом word2vec — вот, например, подробная статья со схемами и матаном.
  • +1
    Как я правильно понимаю похожесть слов «корабль» и «судно» уже встроенны в word2vec?
    • 0
      Ай ай, я уже нашел про модель лексических векторов.
      • +1
        ;)

        >> w2v.similarity("судно_S", "корабль_S")
        
        0.87323218690957494
        
        >> w2v.most_similar(positive=["судно_S"])
        
        [('корабль_S', 0.873232364654541),
         ('шхуна_S', 0.7688922882080078),
         ('пароход_S', 0.7471548914909363),
         ('катер_S', 0.720923662185669),
         ('крейсер_S', 0.6798930764198303),
         ('парусник_S', 0.6786847114562988),
         ('яхта_S', 0.6684943437576294),
         ('фрегат_S', 0.6651678085327148),
         ('шлюпка_S', 0.6553121209144592),
         ('теплоход_S', 0.6479202508926392)]
        
        • +1
          а что судно — утка? (чисто «научный» интерес))… особенно в сравнении с симили судна с другими водоплавающими (например — гусём)
          и потом корабль с ними же…
          • +1
            Утки, гуси, корабли...
            In[23]: w2v.similarity("судно_S", "утка_S")
            Out[23]: 0.089143973072140115
            In[24]: w2v.similarity("судно_S", "гусь_S")
            Out[24]: 0.097027585466394742
            In[25]: w2v.similarity("судно_S", "лебедь_S")
            Out[25]: 0.12152089704781086
            In[26]: w2v.similarity("корабль_S", "утка_S")
            Out[26]: 0.054613116159502359
            In[27]: w2v.similarity("корабль_S", "гусь_S")
            Out[27]: 0.086045645971750101
            In[28]: w2v.similarity("корабль_S", "лебедь_S")
            Out[28]: 0.1518852487994459
            


            При желании можно поиграть с этим онлайн
            • 0
              спасибо, надо пощупать…
  • +2
    Благодаря стараниям коллеги wiygn (не поленился же человек, наковырял изюму :)) корпус пирожков существенно пополнился (теперь их больше 7500). Мусор я, вроде, вычистил, повторы своими кустарными средствами поудалял, однако если какой-нибудь добрый человек найдёт время перепроверить 1.3 мегабайта чистой поэзии — будет вообще хорошо.

    чистая поэзия :)
    >> pprint(similar_poems("чистая поэзия", pm, w2v, topn=5))
    [('из современной русской прозы'
      'я выделил бы тот роман'
      'который был написан вами'
      'а выделив бы удалил',
      0.13792188721288026),
     ('олегу маша показалась'
      'прекрасной чистой и святой'
      'олег же маше показался'
      'в дырявых бежевых носках',
      0.13690850835700927),
     ('когда любовь переполняет'
      'то выливается она'
      'взаимная посредством секса'
      'а безнадежная в стихах',
      0.12459351854737398),
     ('я томик ленина листаю'
      'страницы гладки и чисты'
      'как кожа юной комсомолки'
      'и также пахнут молоком',
      0.12329326742852674),
     ('зухра великое искусство'
      'она нисходит не ко всем'
      'и те кому она даётся'
      'не все овладевают ей',
      0.11324476203692123)]

    • 0
      Ух, как интересно. Могу поделиться базой со своего Поэтория. Думаю теперь, вот, реализовать что-то подобное у себя.
      • 0
        Конечно же делитесь! Это прямо-таки из серии «мечты сбываются» — буквально неделю назад грезил о базе Поэтория :). Кстати, могли бы вы предоставить эту базу вместе с рейтингами — есть огромное желание протащить поэтический материал через машинное обучение на предмет предсказания качества (популярности) пирожка. Поверить, так сказать, алгеброй гармонию — посальерить моцартов :).
        • +1
          Надо было не грезить, а написать сразу :) Отправил контакты в личку.
  • +2
    Опять-таки при содействии wiygn база пирожков существенно подросла (теперь в ней порядка 33000 штук — poems_33000.txt).

    Примеры «насыщенного» поиска по экзотичным словам:

    Бювар
    >> pprint(ap.similar_poems("бювар", pm, w2v, topn=5, use_associations=True))
    [('у программиста две коробки'
      'коробка а коробка бэ'
      'в коробке а коробка бэ а'
      'в коробке бэ коробка а',
      0.38437933799548024),
     ('так и живёт она с котами'
      'фиалками и сундуком'
      'в котором кожаная плётка'
      'и мой забытый портсигар',
      0.35700261151349105),
     ('карандаши лежат в пенале'
      'пенал в портфеле а портфель'
      'на чердаке среди другого'
      'сентиментального нытья',
      0.34135048477737989),
     ('забыл ключи и ноты тоже'
      'и даже паузы забыл'
      'и что за палочка позвольте'
      'лежит в кармане у меня',
      0.3361660286232277),
     ('олег анальные конфеты '
      'купил и бережно несёт '
      'не в рюкзаке и не в барсетке '
      'и даже не в кармане брюк',
      0.32774677611233893)]
    

    Трензель
    >> pprint(ap.similar_poems("трензель", pm, w2v, topn=5, use_associations=True))
    [('не плюйтесь митя не верблюд вы'
      'не ржите фёдор вы не конь'
      'вы иннокентий не курите'
      'ведь вы же вы ж не человек',
      0.35941473642985028),
     ('седлай кобылу вороную'
      'поскачем в крым поскачем в степь'
      'мы тыщу триста километров'
      'преодолеем невзначай',
      0.33290767669677734),
     ('али седлает дромадера'
      'зейнаб и фатима стоят'
      'а может не зейнаб а лейла'
      'в скафандрах чёрных не поймёшь',
      0.33117986192890242),
     ('илья ильич гнедую лошадь'
      'ведет в конюшню под уздцы'
      'и изнутри на две щеколды'
      'надежно запирает дверь',
      0.31826136906941732),
     ('я дискжокей а это значит'
      'люблю пластинки объезжать'
      'бывало как увижу диски'
      'седлаю и скачу верхом',
      0.30559972127278645)]
    

    Елань
    >> pprint(ap.similar_poems("елань", pm, w2v, topn=5, use_associations=True))
    [('мой город спит и видит поле'
      'а мой район в нём видит лес'
      'и речки спят и видят речки'
      'такие же но без имён',
      0.30486257452713816),
     (' разбит мой город на районы'
      'разбит район мой на дома'
      'мой дом разбит немецкой бомбой'
      'а немец нашими разбит',
      0.29329273747462853),
     ('внутри у николая горы'
      'и океаны и леса'
      'снаружи николая тоже'
      'но не такие как внутри',
      0.28508076137966581),
     ('пришли в деревню супостаты'
      'а изуверы в города'
      'а к нам в домишко на отшибе'
      'пришла весна и комсомол',
      0.2843143396210252),
     ('я назарет из иисуса'
      'здесь все в округе города'
      'и все селения поменьше'
      'из иисусов состоят',
      0.27356621071144388)]
    

    Бурлеск
    >> pprint(ap.similar_poems("бурлеск", pm, w2v, topn=5, use_associations=True))
    [('играл чайковского шаинский '
      'не угадаете на чём '
      'ну хорошо не буду мучать '
      'на сцене в пьесе про себя',
      0.22649443591082538),
     ('мы композиторы семёны'
      'мы написали вам сонат'
      'сюит симфоний и секвенций'
      'а вы борщи несите нам',
      0.22268539004855686),
     ('оксане нравилось фламенко'
      'олегу классика и джаз'
      'они вдвоём со сцены пели'
      'про лагеря и мусоров',
      0.22202377988581071),
     ('семён седьмой литературный'
      'известный персонаж подряд'
      'играет молча в грустной пьесе'
      'завязанные рукава',
      0.21163431803385416),
     ('играет мыскина неплохо'
      'неплохо моцарт сочинял'
      'и только секс с тобой прекрасен'
      'с тобой одной с тобой одной',
      0.21109667530766241)]
    

    Фронда
    >> pprint(ap.similar_poems("фронда", pm, w2v, topn=5, use_associations=True))
    [('осталось несколько столетий'
      'и мы построим коммунизм'
      'без мерзкой власти капитала'
      'без войн без секса без людей',
      0.23658270835876466),
     ('имею комплексы и взгляды'
      'а также принципы и вкус'
      'идеи и мировоззренье'
      'в ответ прошу оральный секс',
      0.21776164524138919),
     ('у ольги изменился запах'
      'а кажется что интеллект'
      'и политические взгляды'
      'и форма челки и зубов',
      0.20957694230256257),
     ('власть добрократов под собою'
      'имеют крепких два столба'
      'все то что сочинил шаинский'
      'и политический террор',
      0.20927111307779947),
     ('вступив в сообщество плутархов'
      'я понял что не прогадал'
      'у власти нынче плутократы'
      'а я плутарх я их монарх',
      0.20429160859849718)]
    

    Синекура
    >> pprint(ap.similar_poems("синекура", pm, w2v, topn=5, use_associations=True))
    [('для семинаров по убийству'
      'пособий просто не достать'
      'стипендий ленинских не платят'
      'и блата нет ни у кого',
      0.19780904275399666),
     ('аванс у дъявольской зарплаты'
      'сиеминутен но велик'
      'аванс божественной ничтожен'
      'но даже за чертой нетленн',
      0.19452412923177084),
     ('вступайте в войско чингизхана'
      'оклад семь тыщ двойной паёк'
      'декретный отпукс саноторий'
      'страховка пенсия престиж',
      0.18662718570593631),
     ('олег стоит не понимает'
      'откуда столько голосов'
      'откуда этот свет и гдеже'
      'его зарплата и очки',
      0.18360155600088615),
     ('оксана не дала олегу'
      'олег не дал стране угля'
      'страна не даст врачу зарплату'
      'а врач не даст оксане жить',
      0.1772317091623942)]
    

    Латифундия
    >> pprint(ap.similar_poems("латифундия", pm, w2v, topn=5, use_associations=True))
    [('россия в крепостных у чуба '
      'который айс к людям как лед '
      'он взял в концессию у вовы '
      'продажу света и тепла',
      0.19776902198791504),
     ('герасим крепостного права '
      'четвертый год в деревне нет'
      'уебище глухонемое'
      'перетопил нам всех собак',
      0.19733301798502603),
     ('купил в балашихе участок'
      'построил дом и нанял слуг'
      'и чувствую как неизбежно'
      'я чьей то становлюсь мечтой',
      0.19490887901999734),
     ('сначала я дружил дворами'
      'а после стал дружить семьёй'
      'и коллективом позже дачей'
      'теперь диагнозом дружу',
      0.18583927154541016),
     (' разбит мой город на районы'
      'разбит район мой на дома'
      'мой дом разбит немецкой бомбой'
      'а немец нашими разбит',
      0.17606544494628906)]
    

    Ригоризм
    >> pprint(ap.similar_poems("ригоризм", pm, w2v, topn=5, use_associations=True))
    [('я не люблю себя за скотство'
      'за подлость мелочность и лень'
      'сильней всего конечно бесит'
      'тупая ненависть к себе',
      0.24003094121029503),
     ('адам произошел от бога'
      'и унаследовал его'
      'агрессию и истеричность'
      'и склонность к постоянной лжы',
      0.23890022203034045),
     ('он был не просто так евгений'
      'он был евгений смерть врагу'
      'а кто враги бездушность подлость'
      'мздоимство косность клевета',
      0.23708248138427734),
     ('есть героин для героизма'
      'есть для гашения страстей'
      'гашыш ещо для оптимизма'
      'немного опиума есть',
      0.21587917539808485),
     ('остановитесь я же просто'
      'производитель пирожков'
      'их простота и гениальность'
      'не повод поклоняться мне',
      0.21307498333500882)]
    

    Вертеп
    >> pprint(ap.similar_poems("вертеп", pm, w2v, topn=5, use_associations=True))
    [('а после рюмочной и клуба'
      'еще был винный погребок'
      'избыточный и тошнотворный'
      'как тридцать третье фуэте',
      0.22720870265254267),
     ('в тоннелях метрополитена'
      'есть андерграундный кабак'
      'там крысы пляшут зазывая'
      'самоубийц на огонек',
      0.21550264812651135),
     ('о да завидное местечко'
      'вы подобрали мне но где'
      'здесь магазины бары клубы'
      'и люди все скажите где',
      0.21172858874003092),
     ('то дес то клуб то дес то клуб то'
      'дес то клуб то дес то клуб то'
      'дес то клуб то дес то клуб то дес'
      'то клуб то дес то клуб то дес',
      0.20926956696943802),
     ('оксана ходит с голой жопой'
      'в кафе в химчистку в магазин'
      'ей кажется что так удобней'
      'а люди падают без чувств',
      0.20475262006123859)]
    
  • 0
    Автор Поэтория (пользователь hior) любезно предоставил базу пирожков-порошков (около 56000 — poems.csv — формат [стишок, рейтинг]). За что ему огромное человеческое спасибо.
    • 0
      может прикрутить к Поэторию сервис — «сгенерировать пирожок на тему»?
      • 0
        Да, поэтический оракул (или пирожковый И-Цзин :)) было бы прикольно запустить. Однако на данный момент есть ряд сложностей (впрочем, я ни разу не специалист по прикручиванию сервисов и, быть может, теперь это никакие не сложности). Во-первых, память — нужно порядка 500mb оперативки для загрузки моделей. Во-вторых, скорость — у меня сейчас поиск по 33000 базе занимает от секунды до десяти (в зависимости от количества слов в запросе) и конкретно пригружает все ядра. Можно, конечно, все пирожки заблаговременно представить в формате векторных матриц, но вряд ли это ускорит процесс принципиально.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.