{
    "version": "https:\/\/jsonfeed.org\/version\/1",
    "title": "Блог об аналитике, визуализации данных, data science и BI, заметки с тегом: бордерлайн",
    "home_page_url": "http:\/\/test.leftjoin.ru\/tags\/borderlayn\/",
    "feed_url": "http:\/\/test.leftjoin.ru\/tags\/borderlayn\/json\/",
    "icon": "http:\/\/test.leftjoin.ru\/user\/userpic@2x.jpg",
    "author": {
        "name": "Николай Валиотти",
        "url": "http:\/\/test.leftjoin.ru\/",
        "avatar": "http:\/\/test.leftjoin.ru\/user\/userpic@2x.jpg"
    },
    "items": [
        {
            "id": "100",
            "url": "http:\/\/test.leftjoin.ru\/all\/borderline-text-analysis\/",
            "title": "Python и тексты нового альбома Земфиры: анализируем суть песен",
            "content_html": "<div class=\"e2-text-picture\">\n<img src=\"http:\/\/test.leftjoin.ru\/pictures\/Zemfira_borderline-2.jpg\" width=\"600\" height=\"600\" alt=\"\" \/>\n<\/div>\n<p>Неделю назад вышёл первый за 8 лет студийный альбом Земфиры «Бордерлайн». К работе помимо рок-певицы приложили руку разные люди, в том числе и её родственники — рифф для песни «таблетки» написал её племянник из Лондона. Альбом получился разнообразным: например, песня «остин» посвящена главному персонажу игры Homescapes российской студии Playrix (кстати, посмотрите свежие <a href=\"https:\/\/youtu.be\/SOx8afEUTnE\">Бизнес-секреты с братьями Бухманами<\/a>, там они тоже про это рассказывают) — Земфире нравится игра, и для трека она связалась со студией. А сингл «крым» был написан в качестве саундтрека к новой картине соратницы Земфиры — Ренаты Литвиновой.<\/p>\n<p class=\"note\">Послушать альбом в <a href=\"https:\/\/music.apple.com\/ru\/album\/бордерлайн\/1554865105\">Apple Music<\/a> \/ <a href=\"https:\/\/music.yandex.ru\/album\/14052981\">Яндекс.Музыке<\/a> \/ <a href=\"https:\/\/open.spotify.com\/album\/6khBsXmKA1FKjYVCIBy9kt\">Spotify<\/a><\/p>\n<p>Тем не менее, дух всего альбома довольно мрачен — в песнях часто повторяются слова «боль», «ад», «бесишь» и прочие по смыслу. Мы решили провести разведочный анализ нового альбома, а затем при помощи модели Word2Vec и косинусной меры посмотреть на семантическую близость песен между собой и вычислить общее настроение альбома.<\/p>\n<p>Для тех, кому скучно читать про подготовку данных и шаги анализа можно <a href=\"http:\/\/test.leftjoin.ru\/all\/borderline-text-analysis\/#result\">перейти сразу к результатам<\/a>.<\/p>\n<h2>Подготовка данных<\/h2>\n<p>Для начала работы напишем скрипт обработки данных. Цель скрипта — из множества текстовых файлов, в каждом из которых лежит по песне, собрать единую csv-таблицу. При этом текст треков очищаем от знаков пунктуации и ненужных слов.<\/p>\n<pre class=\"e2-text-code\"><code>import pandas as pd\r\nimport re\r\nimport string\r\nimport pymorphy2\r\nfrom nltk.corpus import stopwords<\/code><\/pre><p>Создаём морфологический анализатор и расширяем список всего, что нужно отбросить:<\/p>\n<pre class=\"e2-text-code\"><code>morph = pymorphy2.MorphAnalyzer()\r\nstopwords_list = stopwords.words('russian')\r\nstopwords_list.extend(['куплет', 'это', 'я', 'мы', 'ты', 'припев', 'аутро', 'предприпев', 'lyrics', '1', '2', '3', 'то'])\r\nstring.punctuation += '—'<\/code><\/pre><p>Названия песен приведены на английском — создадим словарь для перевода на русский и словарь, из которого позднее сделаем таблицу:<\/p>\n<pre class=\"e2-text-code\"><code>result_dict = dict()\r\n\r\nsongs_dict = {\r\n    'snow':'снег идёт',\r\n    'crimea':'крым',\r\n    'mother':'мама',\r\n    'ostin':'остин',\r\n    'abuse':'абьюз',\r\n    'wait_for_me':'жди меня',\r\n    'tom':'том',\r\n    'come_on':'камон',\r\n    'coat':'пальто',\r\n    'this_summer':'этим летом',\r\n    'ok':'ок',\r\n    'pills':'таблетки'\r\n}<\/code><\/pre><p>Опишем несколько функций. Первая читает целиком песню из файла и удаляет переносы строки, вторая очищает текст от ненужных символов и слов, а третья при помощи морфологического анализатора pymorphy2 приводит слова к нормальной форме. Модуль pymorphy2 не всегда хорошо справляется с неоднозначностью — для слов «ад» и «рай» потребуется дополнительная обработка.<\/p>\n<pre class=\"e2-text-code\"><code>def read_song(filename):\r\n    f = open(f'{filename}.txt', 'r').read()\r\n    f = f.replace('\\n', ' ')\r\n    return f\r\n\r\ndef clean_string(text):\r\n    text = re.split(' |:|\\.|\\(|\\)|,|&quot;|;|\/|\\n|\\t|-|\\?|\\[|\\]|!', text)\r\n    text = ' '.join([word for word in text if word not in string.punctuation])\r\n    text = text.lower()\r\n    text = ' '.join([word for word in text.split() if word not in stopwords_list])\r\n    return text\r\n\r\ndef string_to_normal_form(string):\r\n    string_lst = string.split()\r\n    for i in range(len(string_lst)):\r\n        string_lst[i] = morph.parse(string_lst[i])[0].normal_form\r\n        if (string_lst[i] == 'аду'):\r\n            string_lst[i] = 'ад'\r\n        if (string_lst[i] == 'рая'):\r\n            string_lst[i] = 'рай'\r\n    string = ' '.join(string_lst)\r\n    return string<\/code><\/pre><p>Проходим по каждой песне и читаем файл с соответствующим названием:<\/p>\n<pre class=\"e2-text-code\"><code>name_list = []\r\ntext_list = []\r\nfor song, name in songs_dict.items():\r\n    text = string_to_normal_form(clean_string(read_song(song)))\r\n    name_list.append(name)\r\n    text_list.append(text)<\/code><\/pre><p>Затем объединяем всё в DataFrame и сохраняем в виде csv-файла.<\/p>\n<pre class=\"e2-text-code\"><code>df = pd.DataFrame()\r\ndf['name'] = name_list\r\ndf['text'] = text_list\r\ndf['time'] = [290, 220, 187, 270, 330, 196, 207, 188, 269, 189, 245, 244]\r\ndf.to_csv('borderline.csv', index=False)<\/code><\/pre><p>Результат:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"http:\/\/test.leftjoin.ru\/pictures\/1-26.png\" width=\"477\" height=\"365\" alt=\"\" \/>\n<\/div>\n<h2>Облако слов по всему альбому<\/h2>\n<p>Начнём анализ с построения облака слов — оно отобразит, какие слова чаще всего встречаются в песнях. Импортируем нужные библиотеки, читаем csv-файл и устанавливаем конфигурации:<\/p>\n<pre class=\"e2-text-code\"><code>import nltk\r\nfrom wordcloud import WordCloud\r\nimport pandas as pd\r\nimport matplotlib.pyplot as plt\r\nfrom nltk import word_tokenize, ngrams\r\n\r\n%matplotlib inline\r\nnltk.download('punkt')\r\ndf = pd.read_csv('borderline.csv')<\/code><\/pre><p>Теперь создаём новую фигуру, устанавливаем параметры оформления и при помощи библиотеки wordcloud отображаем слова с размером прямо пропорциональным частоте упоминания слова. Над каждым графиком дополнительно указываем название песни.<\/p>\n<pre class=\"e2-text-code\"><code>fig = plt.figure()\r\nfig.patch.set_facecolor('white')\r\nplt.subplots_adjust(wspace=0.3, hspace=0.2)\r\ni = 1\r\nfor name, text in zip(df.name, df.text):\r\n    tokens = word_tokenize(text)\r\n    text_raw = &quot; &quot;.join(tokens)\r\n    wordcloud = WordCloud(colormap='PuBu', background_color='white', contour_width=10).generate(text_raw)\r\n    plt.subplot(4, 3, i, label=name,frame_on=True)\r\n    plt.tick_params(labelsize=10)\r\n    plt.imshow(wordcloud)\r\n    plt.axis(&quot;off&quot;)\r\n    plt.title(name,fontdict={'fontsize':7,'color':'grey'},y=0.93)\r\n    plt.tick_params(labelsize=10)\r\n    i += 1<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"http:\/\/test.leftjoin.ru\/pictures\/2@2x-2.png.jpg\" width=\"2560\" height=\"1707\" alt=\"\" \/>\n<\/div>\n<h2>EDA текстов альбома<\/h2>\n<p>Теперь проанализируем тексты песен — импортируем библиотеки для работы с данными и визуализации:<\/p>\n<pre class=\"e2-text-code\"><code>import plotly.graph_objects as go\r\nimport plotly.figure_factory as ff\r\nfrom scipy import spatial\r\nimport collections\r\nimport pymorphy2\r\nimport gensim\r\n\r\nmorph = pymorphy2.MorphAnalyzer()<\/code><\/pre><p>Сначала посчитаем число слов в каждой песне, число уникальных слов и процентное соотношение:<\/p>\n<pre class=\"e2-text-code\"><code>songs = []\r\ntotal = []\r\nuniq = []\r\npercent = []\r\n\r\nfor song, text in zip(df.name, df.text):\r\n    songs.append(song)\r\n    total.append(len(text.split()))\r\n    uniq.append(len(set(text.split())))\r\n    percent.append(round(len(set(text.split())) \/ len(text.split()), 2) * 100)<\/code><\/pre><p>А теперь составим из этого DataFrame и дополнительно посчитаем число слов в минуту для каждой песни:<\/p>\n<pre class=\"e2-text-code\"><code>df_words = pd.DataFrame()\r\ndf_words['song'] = songs\r\ndf_words['total words'] = total\r\ndf_words['uniq words'] = uniq\r\ndf_words['percent'] = percent\r\ndf_words['time'] = df['time']\r\ndf_words['words per minute'] = round(total \/ (df['time'] \/\/ 60))\r\ndf_words = df_words[::-1]<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"http:\/\/test.leftjoin.ru\/pictures\/3-21.png\" width=\"480\" height=\"369\" alt=\"\" \/>\n<\/div>\n<p>Данные хорошо бы визуализировать — построим две столбиковые диаграммы: одну для числа слов в песне, а другую для числа слов в минуту.<\/p>\n<pre class=\"e2-text-code\"><code>colors_1 = ['rgba(101,181,205,255)'] * 12\r\ncolors_2 = ['rgba(62,142,231,255)'] * 12\r\n\r\nfig = go.Figure(data=[\r\n    go.Bar(name='📝 Всего слов',\r\n           text=df_words['total words'],\r\n           textposition='auto',\r\n           x=df_words.song,\r\n           y=df_words['total words'],\r\n           marker_color=colors_1,\r\n           marker=dict(line=dict(width=0)),),\r\n    go.Bar(name='🌀 Уникальных слов',\r\n           text=df_words['uniq words'].astype(str) + '&lt;br&gt;'+ df_words.percent.astype(int).astype(str) + '%' ,\r\n           textposition='inside',\r\n           x=df_words.song,\r\n           y=df_words['uniq words'],\r\n           textfont_color='white',\r\n           marker_color=colors_2,\r\n           marker=dict(line=dict(width=0)),),\r\n])\r\n\r\nfig.update_layout(barmode='group')\r\n\r\nfig.update_layout(\r\n    title = \r\n        {'text':'&lt;b&gt;Соотношение числа уникальных слов к общему количеству&lt;\/b&gt;&lt;br&gt;&lt;span style=&quot;color:#666666&quot;&gt;&lt;\/span&gt;'},\r\n    showlegend = True,\r\n    height=650,\r\n    font={\r\n        'family':'Open Sans, light',\r\n        'color':'black',\r\n        'size':14\r\n    },\r\n    plot_bgcolor='rgba(0,0,0,0)',\r\n)\r\nfig.update_layout(legend=dict(\r\n    yanchor=&quot;top&quot;,\r\n    xanchor=&quot;right&quot;,\r\n))\r\n\r\nfig.show()<\/code><\/pre><iframe id=\"igraph\" scrolling=\"no\" style=\"border:none;\" seamless=\"seamless\" src=\"https:\/\/plotly.com\/~Elisejj\/76.embed?showlink=false\" height=\"650\" width=\"100%\"><\/iframe>\n<pre class=\"e2-text-code\"><code>colors_1 = ['rgba(101,181,205,255)'] * 12\r\ncolors_2 = ['rgba(238,85,59,255)'] * 12\r\n\r\nfig = go.Figure(data=[\r\n    go.Bar(name='⏱️ Длина трека, мин.',\r\n           text=round(df_words['time'] \/ 60, 1),\r\n           textposition='auto',\r\n           x=df_words.song,\r\n           y=-df_words['time'] \/\/ 60,\r\n           marker_color=colors_1,\r\n           marker=dict(line=dict(width=0)),\r\n          ),\r\n    go.Bar(name='🔄 Слов в минуту',\r\n           text=df_words['words per minute'],\r\n           textposition='auto',\r\n           x=df_words.song,\r\n           y=df_words['words per minute'],\r\n           marker_color=colors_2,\r\n           textfont_color='white',\r\n           marker=dict(line=dict(width=0)),\r\n          ),\r\n])\r\n\r\nfig.update_layout(barmode='overlay')\r\n\r\nfig.update_layout(\r\n    title = \r\n        {'text':'&lt;b&gt;Длина трека и число слов в минуту&lt;\/b&gt;&lt;br&gt;&lt;span style=&quot;color:#666666&quot;&gt;&lt;\/span&gt;'},\r\n    showlegend = True,\r\n    height=650,\r\n    font={\r\n        'family':'Open Sans, light',\r\n        'color':'black',\r\n        'size':14\r\n    },\r\n    plot_bgcolor='rgba(0,0,0,0)'\r\n)\r\n\r\n\r\nfig.show()<\/code><\/pre><iframe id=\"igraph\" scrolling=\"no\" style=\"border:none;\" seamless=\"seamless\" src=\"https:\/\/plotly.com\/~Elisejj\/78.embed?showlink=false\" height=\"650\" width=\"100%\"><\/iframe>\n<h2>Работа с Word2Vec моделью<\/h2>\n<p>При помощи модуля gensim загружаем модель, указывая на бинарный файл:<\/p>\n<pre class=\"e2-text-code\"><code>model = gensim.models.KeyedVectors.load_word2vec_format('model.bin', binary=True)<\/code><\/pre><p class=\"note\">Для материала мы использовали готовую обученную на Национальном Корпусе Русского Языка модель от сообщества <a href=\"https:\/\/rusvectores.org\/ru\/models\/\">RusVectōrēs<\/a><\/p>\n<p>Модель Word2Vec основана на нейронных сетях и позволяет представлять слова в виде векторов, учитывая семантическую составляющую. Это означает, что если мы возьмём два слова — например, «мама» и «папа», представим их в виде двух векторов и посчитаем косинус, значения будет близко к 1. Аналогично, у двух слов, не имеющих ничего общего по смыслу косинусная мера близка к 0.<\/p>\n<p>Опишем функцию get_vector: она будет принимать список слов, распознавать для каждого часть речи, а затем получать и суммировать вектора — так мы сможем находить вектора не для одного слова, а для целых предложений и текстов.<\/p>\n<pre class=\"e2-text-code\"><code>def get_vector(word_list):\r\n    vector = 0\r\n    for word in word_list:\r\n        pos = morph.parse(word)[0].tag.POS\r\n        if pos == 'INFN':\r\n            pos = 'VERB'\r\n        if pos in ['ADJF', 'PRCL', 'ADVB', 'NPRO']:\r\n            pos = 'NOUN'\r\n        if word and pos:\r\n            try:\r\n                word_pos = word + '_' + pos\r\n                this_vector = model.word_vec(word_pos)\r\n                vector += this_vector\r\n            except KeyError:\r\n                continue\r\n    return vector<\/code><\/pre><p>Для каждой песни находим вектор и собираем соответствующий столбец в DataFrame:<\/p>\n<pre class=\"e2-text-code\"><code>vec_list = []\r\nfor word in df['text']:\r\n    vec_list.append(get_vector(word.split()))\r\ndf['vector'] = vec_list<\/code><\/pre><p>Теперь сравним вектора между собой, посчитав их косинусную близость. Те песни, у которых косинусная метрика выше 0,5 запомним отдельно — так мы получим самые близкие пары песен. Данные о сравнении векторов запишем в двумерный список result.<\/p>\n<pre class=\"e2-text-code\"><code>similar = dict()\r\nresult = []\r\nfor song_1, vector_1 in zip(df.name, df.vector):\r\n    sub_list = []\r\n    for song_2, vector_2 in zip(df.name.iloc[::-1], df.vector.iloc[::-1]):\r\n        res = 1 - spatial.distance.cosine(vector_1, vector_2)\r\n        if res &gt; 0.5 and song_1 != song_2 and (song_1 + ' \/ ' + song_2 not in similar.keys() and song_2 + ' \/ ' + song_1 not in similar.keys()):\r\n            similar[song_1 + ' \/ ' + song_2] = round(res, 2)\r\n        sub_list.append(round(res, 2))\r\n    result.append(sub_list)<\/code><\/pre><p>Самые похожие треки соберём в отдельный DataFrame:<\/p>\n<pre class=\"e2-text-code\"><code>df_top_sim = pd.DataFrame()\r\ndf_top_sim['name'] = list(similar.keys())\r\ndf_top_sim['value'] = list(similar.values())\r\ndf_top_sim.sort_values(by='value', ascending=False)<\/code><\/pre><p>И построим такой же bar chart:<\/p>\n<pre class=\"e2-text-code\"><code>colors = ['rgba(101,181,205,255)'] * 5\r\n\r\nfig = go.Figure([go.Bar(x=df_top_sim['name'],\r\n                        y=df_top_sim['value'],\r\n                        marker_color=colors,\r\n                        width=[0.4,0.4,0.4,0.4,0.4],\r\n                        text=df_top_sim['value'],\r\n                        textfont_color='white',\r\n                        textposition='auto')])\r\n\r\nfig.update_layout(\r\n    title = \r\n        {'text':'&lt;b&gt;Топ-5 схожих песен&lt;\/b&gt;&lt;br&gt;&lt;span style=&quot;color:#666666&quot;&gt;&lt;\/span&gt;'},\r\n    showlegend = False,\r\n    height=650,\r\n    font={\r\n        'family':'Open Sans, light',\r\n        'color':'black',\r\n        'size':14\r\n    },\r\n    plot_bgcolor='rgba(0,0,0,0)',\r\n    xaxis={'categoryorder':'total descending'}\r\n)\r\n\r\nfig.show()<\/code><\/pre><iframe id=\"igraph\" scrolling=\"no\" style=\"border:none;\" seamless=\"seamless\" src=\"https:\/\/plotly.com\/~Elisejj\/80.embed?showlink=false\" height=\"650\" width=\"100%\"><\/iframe>\n<p>Имея вектор каждой песни, давайте посчитаем вектор всего альбома — сложим вектора песен. Затем для такого вектора при помощи модели получим самые близкие по духу и смыслу слова.<\/p>\n<pre class=\"e2-text-code\"><code>def get_word_from_tlist(lst):\r\n    for word in lst:\r\n        word = word[0].split('_')[0]\r\n        print(word, end=' ')\r\n\r\nvec_sum = 0\r\nfor vec in df.vector:\r\n    vec_sum += vec\r\nsim_word = model.similar_by_vector(vec_sum)\r\nget_word_from_tlist(sim_word)<\/code><\/pre><p><span style=\"color: '#65b5cd'; font-size: 1.2em\"><b>небо тоска тьма пламень плакать горе печаль сердце солнце мрак<\/b><\/span><\/p>\n<p>Наверное, это ключевой результат и описание альбома Земфиры всего лишь в 10 словах.<\/p>\n<p>Наконец, построим общую тепловую карту, каждая ячейка которой — результат сравнения косинусной мерой текстов двух треков.<\/p>\n<pre class=\"e2-text-code\"><code>colorscale=[[0.0, &quot;rgba(255,255,255,255)&quot;],\r\n            [0.1, &quot;rgba(229,232,237,255)&quot;],\r\n            [0.2, &quot;rgba(216,222,232,255)&quot;],\r\n            [0.3, &quot;rgba(205,214,228,255)&quot;],\r\n            [0.4, &quot;rgba(182,195,218,255)&quot;],\r\n            [0.5, &quot;rgba(159,178,209,255)&quot;],\r\n            [0.6, &quot;rgba(137,161,200,255)&quot;],\r\n            [0.7, &quot;rgba(107,137,188,255)&quot;],\r\n            [0.8, &quot;rgba(96,129,184,255)&quot;],\r\n            [1.0, &quot;rgba(76,114,176,255)&quot;]]\r\n\r\nfont_colors = ['black']\r\nx = list(df.name.iloc[::-1])\r\ny = list(df.name)\r\nfig = ff.create_annotated_heatmap(result, x=x, y=y, colorscale=colorscale, font_colors=font_colors)\r\nfig.show()<\/code><\/pre><iframe id=\"igraph\" scrolling=\"no\" style=\"border:none;\" seamless=\"seamless\" src=\"https:\/\/plotly.com\/~Elisejj\/82.embed?showlink=false\" height=\"650\" width=\"100%\"><\/iframe>\n<h2><a name=\"result\">Результаты анализа и интерпретация данных<\/a><\/h2>\n<p>Давайте ещё раз посмотрим на всё, что у нас получилось — начнём с облака слов. Нетрудно заметить, что у слов «боль», «невозможно», «сорваться», «растерзаны», «сложно», «терпеть», «любить» размер весьма приличный — всё потому, что такие слова встречаются часто на протяжении всего текста песен:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"http:\/\/test.leftjoin.ru\/pictures\/2@2x-2.png-1.jpg\" width=\"2560\" height=\"1707\" alt=\"\" \/>\n<\/div>\n<p>Одной из самых «разнообразных» песен оказался сингл «крым» — в нём 74% уникальных слов. А в песне «снег идёт» слов совсем мало, поэтому большинство — 82% уникальны. Самой большой песней в альбоме получился трек «таблетки» — суммарно там около 150 слов.<\/p>\n<iframe id=\"igraph\" scrolling=\"no\" style=\"border:none;\" seamless=\"seamless\" src=\"https:\/\/plotly.com\/~Elisejj\/76.embed?showlink=false\" height=\"650\" width=\"100%\"><\/iframe>\n<p>Как было выяснено на прошлом графике, самый «динамичный» трек — «таблетки», целых 37 слов в минуту — практически по слову на каждые две секунды. А самый длинный трек — «абъюз», в нём же и согласно предыдущему графику практически самый низкий процент уникальных слов — 46%.<\/p>\n<iframe id=\"igraph\" scrolling=\"no\" style=\"border:none;\" seamless=\"seamless\" src=\"https:\/\/plotly.com\/~Elisejj\/78.embed?showlink=false\" height=\"650\" width=\"100%\"><\/iframe>\n<p>Топ-5 самых семантически похожих пар текстов:<\/p>\n<iframe id=\"igraph\" scrolling=\"no\" style=\"border:none;\" seamless=\"seamless\" src=\"https:\/\/plotly.com\/~Elisejj\/80.embed?showlink=false\" height=\"650\" width=\"100%\"><\/iframe>\n<p>Ещё мы получили вектор всего альбома и подобрали самые близкие слова. Только посмотрите на них — «тьма», «тоска», «плакать», «горе», «печаль», «сердце» — это же ведь и есть тот перечень слов, который характеризует лирику Земфиры!<\/p>\n<p><span style=\"color: '#65b5cd'; font-size: 1.2em\"><b>небо тоска тьма пламень плакать горе печаль сердце солнце мрак<\/b><\/span><\/p>\n<p>Финал — тепловая карта. По визуализации заметно, что практически все песни достаточно схожи между собой — косинусная мера у многих пар превышает значение в 0.4.<\/p>\n<iframe id=\"igraph\" scrolling=\"no\" style=\"border:none;\" seamless=\"seamless\" src=\"https:\/\/plotly.com\/~Elisejj\/82.embed?showlink=false\" height=\"650\" width=\"100%\"><\/iframe>\n<h2>Выводы<\/h2>\n<p>В материале мы провели EDA всего текста нового альбома и при помощи предобученной модели Word2Vec доказали гипотезу — большинство песен «бордерлайна» пронизывают довольно мрачные и тексты. И это нормально, ведь Земфиру мы любим именно за искренность и прямолинейность.<\/p>\n",
            "date_published": "2021-03-05T19:54:06+03:00",
            "date_modified": "2021-03-08T17:47:56+03:00",
            "image": "http:\/\/test.leftjoin.ru\/pictures\/Zemfira_borderline.jpg",
            "_date_published_rfc2822": "Fri, 05 Mar 2021 19:54:06 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "100",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css",
                    "system\/library\/highlight\/highlight.js",
                    "system\/library\/highlight\/highlight.css"
                ],
                "og_images": [
                    "http:\/\/test.leftjoin.ru\/pictures\/Zemfira_borderline.jpg",
                    "http:\/\/test.leftjoin.ru\/pictures\/Zemfira_borderline-2.jpg",
                    "http:\/\/test.leftjoin.ru\/pictures\/1-26.png",
                    "http:\/\/test.leftjoin.ru\/pictures\/2@2x-2.png.jpg",
                    "http:\/\/test.leftjoin.ru\/pictures\/3-21.png",
                    "http:\/\/test.leftjoin.ru\/pictures\/2@2x-2.png-1.jpg"
                ]
            }
        }
    ],
    "_e2_version": 3365,
    "_e2_ua_string": "E2 (v3365; Aegea)"
}