Короткая история метода


В короткой публикации [1] под названием “Авторство писателей можно узнать по специальной формуле” сообщалось, что в научном издании «New Journal of Physics», группа шведских физиков из университета Умео под руководством Себастьяна Бернгардсона описала новый метод, который позволяет на основе статистических данных определить автора текста. Исследователи проверяли, как в текстах трех писателей — Томаса Харди, Генри Мелвилла и Дэвида Лоуренса — реализуется так называемый закон Ципфа. Исследователи обнаружили, что частота появления новых слов по мере роста объема текста меняется у разных авторов по-разному, причем эта закономерность не зависит от конкретного текста, а только от автора.

Это сообщение было опубликовано 11.12.2009, а, более двадцати лет тому назад, Джон Чарльз Бейкер [2] ввел единицу для измерения способности автора использовать новые слова (здесь понятие «новые» трактуется как ранее не используемые в данном тексте). Джон доказал, что указанная единица является индивидуальной характеристикой автора.

В периодических изданиях и в сети отсутствует информация о реализации закона Зипфа для определения авторства. Поэтому моя работа является первым научным исследованием в указанной области.

Полный код программы


#!/usr/bin/python
# -*- coding: utf-8 -*-
import nltk
from nltk import *
from nltk.corpus import brown
stop_words= nltk.corpus.stopwords.words('english')
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['font.family'] = 'fantasy'
mpl.rcParams['font.fantasy'] = 'Comic Sans MS, Arial'
from nltk.stem import SnowballStemmer
stop_symbols = '.,!?:;"-\n\r()'
def comor_text():
        # функция стемминга NLTK - быстрее яем словарна лемитизация
        stemmer = SnowballStemmer('english')
        # контроль корректности данных  
        if len(txt.get(1.0,END))!=1 and len(txt1.get(1.0,END))!=1 and len(txt2.get(1.0,END))!=1:
                mrus=[txt.get(1.0,END),txt1.get(1.0,END),txt2.get(1.0,END)]
                mr=3 # переменная для раздельного анализа графиков
        elif len(txt.get(1.0,END))!=1 and len(txt1.get(1.0,END))!=1 and len(txt2.get(1.0,END))==1:
                mrus=[txt.get(1.0,END),txt1.get(1.0,END)]
                mr=2                                                                   
        elif len(txt.get(1.0,END))!=1 and len(txt1.get(1.0,END))==1 and len(txt2.get(1.0,END))==1:
                mrus=[txt.get(1.0,END)]
                mr=1                                                              
        else:
                  txt3.insert(END,"There are no all texts")
                  return
        # стемминг, отбор стоп слов и создание частотных словарей
        for text in mrus:            
                v=([stemmer.stem(x) for x in [y.strip(stop_symbols) for y in text.lower().split()] if x and (x not in stop_words)])
                #частотный словарь частота употребления слова - ранг
                my_dictionary=dict([])
                z=[]
                for w in v:
                         if w in my_dictionary:
                                 my_dictionary[w]+=1
                         else:
                                 my_dictionary[w]=1                           
                max_count=int(txt5.get(1.0,END))
                min_count=int(txt4.get(1.0,END))
                if len(my_dictionary)<max_count:
                        txt3.insert(END,"It is not enough of words for the analysis ")
                        return  
                #частотный словарь частота употребления слова - колличество слов
                my_dictionary_z=dict([])         
                for key,val in my_dictionary.items():
                        if val in my_dictionary_z:
                                 my_dictionary_z[val]+=1
                        else:
                                 my_dictionary_z[val]=1
                        z.append(val)
                z.sort(reverse=True)
                # получение исходных данных для построения графиков частотного распределения
                e=z[ min_count:max_count]
                ee=[my_dictionary_z[val] for val in z][ min_count:max_count]
                ee=np.arange(len(my_dictionary))[ min_count:max_count]
                if text==mrus[0]: # расчёт гиперболическойй аппроксимации -a,b для первого документа + % новых слов
                        zz=round((float(len(my_dictionary))*100)/(float(len(v))),0)
                        tt=('In total of words (Text-1) --%i. New words --%i. Percen new words-- %i'%( len(v),len( my_dictionary),int(zz)))
                        xData1 = ee
                        yData1 = e
                        z=[1/w for w in  ee]
                        z1=[(1/w)**2 for w in  ee]
                        t=[ round(e[i]/ee[i],4)  for i in range(0,len(ee)) ]                       
                        a=round((sum(e)*sum(z1)-sum(z)*sum(t))/(len(ee)*sum(z1)-sum(z)**2),3)
                        b=round((len(ee)*sum(t)-sum(z)*sum(e))/(len(ee)*sum(z1)-sum(z)**2),3)
                        y1=[round(a+b/w ,4) for w in ee]
                        s=[round((y1[i]-e[i])**2,4) for i in range(0,len(ee))]
                        sko=round(round((sum(s)/(len(ee)-1))**0.5,4)/(sum(y1)/len(ee)),4)
                        tg='Factor --a  '+str(a)+'  Factor--b  '+str(b)+' Mistake of approximation--  '+str(sko)+"%"+"\n"+tt
                        txt3.delete(1.0, END)
                        txt3.insert(END,tg)
                        txt3.insert(END,'\n')
                        y1Data1=y1
                elif text==mrus[1]:# расчёт аппроксимации -a,b для втого документа + % новых слов
                        zz=round((float(len(my_dictionary))*100)/(float(len(v))),0)
                        tt=('In total of words (Text-2) --%i. New words --%i. Percent new words-- %i'%( len(v),len( my_dictionary),int(zz)))
                        xData2 = ee
                        yData2=e
                        z=[1/w for w in  ee]
                        z1=[(1/w)**2 for w in  ee]
                        t=[ round(e[i]/ee[i],4)  for i in range(0,len(ee)) ]                       
                        a=round((sum(e)*sum(z1)-sum(z)*sum(t))/(len(ee)*sum(z1)-sum(z)**2),3)
                        b=round((len(ee)*sum(t)-sum(z)*sum(e))/(len(ee)*sum(z1)-sum(z)**2),3)
                        y1=[round(a+b/w ,4) for w in ee]
                        s=[round((y1[i]-e[i])**2,4) for i in range(0,len(ee))]
                        sko=round(round((sum(s)/(len(ee)-1))**0.5,4)/(sum(y1)/len(ee)),4)
                        tg='Factor --a  '+str(a)+'  Factor--b  '+str(b)+' Mistake of approximation--  '+str(sko)+"%"+"\n"+tt
                        txt3.insert(END,tg)
                        txt3.insert(END,'\n')
                        y1Data2=y1
                elif text==mrus[2]:# расчёт аппроксимации -a,b для третьего документа + % новых слов
                        zz=round((float(len(my_dictionary))*100)/(float(len(v))),0)
                        tt=('In total of words (Text-3) --%i. New words --%i. Percent new words-- %i'%( len(v),len( my_dictionary),int(zz)))
                        xData3 = ee
                        yData3=e
                        z=[1/w for w in  ee]
                        z1=[(1/w)**2 for w in  ee]
                        t=[ round(e[i]/ee[i],4)  for i in range(0,len(ee)) ]                       
                        a=round((sum(e)*sum(z1)-sum(z)*sum(t))/(len(ee)*sum(z1)-sum(z)**2),3)
                        b=round((len(ee)*sum(t)-sum(z)*sum(e))/(len(ee)*sum(z1)-sum(z)**2),3)
                        y1=[round(a+b/w ,4) for w in ee]
                        s=[round((y1[i]-e[i])**2,4) for i in range(0,len(ee))]
                        sko=round(round((sum(s)/(len(ee)-1))**0.5,4)/(sum(y1)/len(ee)),4)
                        tg='Factor --a  '+str(a)+'  Factor--b  '+str(b)+' Mistake of approximation--  '+str(sko)+"%"+"\n"+tt
                        txt3.insert(END,tg)
                        txt3.insert(END,'\n')
                        y1Data3=y1
        if mr==3: # построение графиков для первого и третьего документа + среднее расстояние между их аппроксимацией 
                r12=round(sum([abs(yData1[i]-yData2[i]) for i in range(0,len(xData1))])/len(xData1),3)               
                txt3.insert(END,"Average distances between art products of the author K--"+ str(r12))
                txt3.insert(END,'\n')
                r13=round(sum([abs(yData1[i]-yData3[i]) for i in range(0,len(xData1))])/len(xData1),3)        
                txt3.insert(END,"Average distance between art products of the authors K and M--"+ str(r13))
                txt3.insert(END,'\n')      
                plt.title('Distribution of frequencies of use of words in the text', size=14)
                plt.xlabel('Serial number of new words', size=14)
                plt.ylabel('Frequency of the use of new words', size=14)
                plt.plot(xData1, yData1, color='r', linestyle=' ', marker='o', label='Test art product of the author -К')
                plt.plot(xData1, y1Data1, color='r',linewidth=2, label='Approximation of hyperbola y=(b/x)+a')
                plt.plot(xData2, yData2, color='g', linestyle=' ', marker='o', label='Comparable art product of the author -К')
                plt.plot(xData2, y1Data2, color='g',linewidth=2, label='Approximation of hyperbola y=(b/x)+a')
                plt.plot(xData3, yData3, color='b', linestyle=' ', marker='o', label='Art product of the author -М')
                plt.plot(xData3, y1Data3, color='b',linewidth=2, label='Approximation of hyperbola y=(b/x)+a')
                plt.legend(loc='best')
                plt.grid(True)
                plt.show()
        elif mr==2:# построение графиков для первого и второго документа + среднее расстояние между их аппроксимацией 
                r12=round(sum([abs(yData1[i]-yData2[i]) for i in range(0,len(xData1))])/len(xData1),3)               
                txt3.insert(END,"Average distances between art products of the author K--"+ str(r12))
                txt3.insert(END,'\n')
                plt.title('Distribution of frequencies of use of words in the text', size=14)
                plt.xlabel('Serial number of new words', size=14)
                plt.ylabel('Frequency of the use of new words', size=14)
                plt.plot(xData1, yData1, color='r', linestyle=' ', marker='o', label='Test art product of the author -К')
                plt.plot(xData1, y1Data1, color='r',linewidth=2, label='Approximation of hyperbola y=(a/x)+b')
                plt.plot(xData2, yData2, color='g', linestyle=' ', marker='o', label='Comparable art product of the author -К')
                plt.plot(xData2, y1Data2, color='g',linewidth=2, label='Approximation of hyperbola y=(a/x)+b')
                plt.legend(loc='best')
                plt.grid(True)
                plt.show()
        elif mr==1: # построение графика для любого загруженного документа
                plt.title('Distribution of frequencies of use of words in the text', size=14)
                plt.xlabel('Serial number of new words', size=14)
                plt.ylabel('Frequency of the use of new words', size=14)
                plt.plot(xData1, yData1, color='r', linestyle=' ', marker='o', label='Test art product of the author -К')
                plt.plot(xData1, y1Data1, color='r',linewidth=2, label='Approximation of hyperbola y=(a/x)+b')                                                                        
                plt.grid(True)
                plt.show()
def choice_text():# загрузка документов в поля формы
                try:
                        op = askopenfilename()
                        f=open(op, 'r')
                        st=f.read()
                        f.close()
                        if len(txt.get(1.0,END))==1:
                                txt.insert(END,st)                                  
                        elif len(txt1.get(1.0,END))==1:
                                txt1.insert(END,st)
                        elif len(txt2.get(1.0,END))==1:
                                txt2.insert(END,st)                      
                except:
                        pass
def array_text_1 ():# чтение данных из поля уже в UNICODE
        if len(txt.get(1.0,END))!=1:
                u=txt.get(1.0,END)
        else:
               txt3.insert(END,"There are no text №1")
               return
        op=1
        processing_subjects (u,op)
def array_text_2 ():# чтение данных из поля уже в UNICODE
        if  len(txt1.get(1.0,END))!=1:
                u=txt1.get(1.0,END)
        else:
               txt3.insert(END,"There are no text №2")
               return
        op=2
        processing_subjects (u,op)
def array_text_3 ():# чтение данных из поля уже в UNICODE
        if len(txt2.get(1.0,END))!=1:
                u=txt2.get(1.0,END)
        else:
               txt3.insert(END,"There are no  text №3")
               return
        op=3
        processing_subjects (u,op)                
def processing_subjects (u,op):# определние жанра текста ( NLTK+corpusbrown) 
        q= nltk.word_tokenize(u)
        qq=[w for w in q if len(w)>2]
        z=nltk.pos_tag(qq)
        m=[w[0].lower() for w in z if w[1]=="NN"]
        d={}
        for w in m:
                if w in d:
                        d[w]+=1
                else:
                        d[w]=1
        pairs = list(d.items())
        pairs.sort(key=lambda x: x[1], reverse=True)
        modals=[]
        wq=10
        for i in pairs[0:wq]:
                modals.append(i[0])           
        cfd = nltk.ConditionalFreqDist(
                        (genre, word)
                        for genre in brown.categories()
                        for word in brown.words(categories=genre))
        #задание жанров для определения
        genres=['news', 'editorial', 'reviews', 'religion', 'hobbies', 'lore', 'belles_lettres',
        'government', 'learned', 'fiction', 'mystery', 'science_fiction', 'adventure', 'romance', 'humor']
        sys.stdout = open('out.txt', 'w')
        cfd.tabulate(conditions=genres, samples=modals)     
        sys.stdout.close()# перенаправление потоков  
        f=open('out.txt', 'r')
        w=f.read()
        txt3.insert(END,w)     
        f.close()
        sys.stdout = open('out.txt', 'w')
        cfd.tabulate(conditions=genres, samples=modals)     
        sys.stdout.close() 
        f=open('out.txt', 'r')
        b=0
        u={}
        for i in f:
                b=b+1
                if b>=2:
                        d=i.split()
                        c=d[1:len(d)]
                        e=[int(w) for w in c]
                        u[d[0]]=sum(e)
        for key, val in u.items():
                if val == max(u.values()):
                      tex="Text № -%i- Theme-- %s. Concurrences- %i"%(op,key,val)
        txt3.insert(END,tex)
        txt3.insert(END,'\n')
        f.close()
        cfd.plot(conditions=genres, samples=modals)     
def close_win():
    tk.destroy()
# интерфейс tkinter + меню+индивидуальная цветоовая разметка текстов+ центрирование формы
import tkinter as T
from tkinter.filedialog import *
import tkinter.filedialog
import fileinput
tk=T.Tk()
tk.geometry('630x630')
main_menu = Menu(tk)
tk.config(menu=main_menu)
file_menu = Menu(main_menu)
main_menu.add_cascade(label="The comparative analysis of the art texts", menu=file_menu)
file_menu.add_command(label="Choice of the texts", command=choice_text)
file_menu.add_command(label="Definition of subjects of the text-1", command=array_text_1)
file_menu.add_command(label="Definition of subjects of the text-2", command=array_text_2)
file_menu.add_command(label="Definition of subjects of the text-3", command=array_text_3)
file_menu.add_command(label="Definition of the author of the text", command=comor_text)
file_menu.add_command(label="Exit  from the program", command=close_win)
lab =Label(tk, text="The text for comparison  author -K ", font=("Arial", 12,  "bold "),foreground='red')
lab.pack()
txt= Text(tk, width=66,height=5,font=("Arial", 12,  "bold "),foreground='red',wrap=WORD)
txt.pack() 
lab1 = Label(tk, text="The test  author -K",font=("Arial", 12,  "bold "),foreground='green')
lab1.pack()
txt1= Text(tk, width=66,height=5,font=("Arial", 12,  "bold "),foreground='green',wrap=WORD)
txt1.pack()
lab2 = Label(tk, text="The text  author-M", font=("Arial", 12,  "bold "),foreground='blue')
lab2.pack()
txt2= Text(tk, width=66,height=5,font=("Arial", 12,  "bold "),foreground='blue',wrap=WORD)
txt2.pack()
lab3 = Label(tk, text="Text results of comparison", font=("Arial", 12,  "bold"),foreground='black')
lab3.pack()
txt3= Text(tk, width=66,height=6,font=("Arial", 12,  "bold"),foreground='black',wrap=WORD)
txt3.pack()
lab4 = Label(tk, text="Minimum quantity of words in a window ", font=("Arial", 12,  "bold"),foreground='black')
lab4.pack()
txt4= Text(tk, width=8,height=1,font=("Arial", 12,  "bold"),foreground='black',wrap=WORD)
wd=10
txt4.pack()
txt4.insert(END,wd)
lab5 = Label(tk, text="Maximum quantity of words in a window ", font=("Arial", 12,  "bold"),foreground='black')
lab5.pack()
txt5= Text(tk, width=8,height=1,font=("Arial", 12,  "bold"),foreground='black',wrap=WORD)
wd=90
txt5.pack()
txt5.insert(END,wd)
tk.title('The analysis of the art text')
x = (tk.winfo_screenwidth() - tk.winfo_reqwidth()) /4#центрирование формы
y = (tk.winfo_screenheight() - tk.winfo_reqheight()) / 16#центрирование формы
tk.wm_geometry("+%d+%d" % (x, y))#центрирование формы
tk.mainloop()                 


Возможности разработанной мной программой:

  1. Возможность раздельного анализа по первому и второму закону Зипфа каждого документа.
  2. Возможность отдельно определить жанр каждого документа (реализация с перераспределением потока данных).
  3. Подвижное, динамическое окно для выбора участка ранга или количества слов непосредственно в процессе анализа.
  4. Цветовая разметка анализируемых документов с их графической реализацией.
  5. Возможность внесения изменений в документ непосредственно в процессе анализа (при наличии в документе не индифицируемых символов).


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

Приведен сравнительный анализ произведений Дэн Броун «Код Давинчи» и «Ангелы и демоны» и Роберт Ладлэм «Идентификация борна»

Интерфейс программы



Gример для сравнительного анализа на авторство произведений Дэна Броуна и Роберта Ладлэма.


Распечатка результатов




График




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

Для определения жанра произведений выбираем из текста произведения ключевые существительные или модальные глаголы. Это могут быть как отдельные слова, так и словосочетания. Из специально размеченного корпуса (я использовал Brown). По максимальному числу вхождений отобранных слов определяется жанр.

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



Распечатка результатов


Factor --a  91.184  Factor--b  2297.14 Mistake of approximation--  0.0511%
In total of words (Text-1) --81020. New words --11120. Percent new words-- 14
Factor --a  100.21  Factor--b  2869.22 Mistake of approximation--  0.0965%
In total of words (Text-2) --86079. New words --11868. Percent new words-- 14
Factor --a  154.162  Factor--b  4982.418 Mistake of approximation--  0.0433%
In total of words (Text-3) --128217. New words --10626. Percent new words-- 8
Average distances between art products of the author K--25.062
Average distance between art products of the authors K and M--138.25

График для сравнения




Из приведенной распечатки и графика видна индивидуальность авторов K –зелёная и красная кривые и М – синяя кривая. Среднее расстояние между аппроксимирующими гиперболами автора К составляет 25,062, а между первым произведением автора К и произведением автора М — 138,25.

Программа строит фрагмент для количества слов от 10 до 90 по второму Закону Зипфа - «количество — частота» [4]. Зипф установил, что частота и количество слов, входящих в текст с этой частотой, тоже связаны между собой.

Специальная формула




  • - коэффициенты гиперболической аппроксимации и погрешности аппроксимации для автора К;

  • - коэффициенты гиперболической аппроксимации и погрешность аппроксимации для автора M;



  • - диапазон для количества слов настраиваемый в процессе анализа графика.

Неравенство (1) я проверил на 50 тройках произведениях англоязычных авторов. Большей статистики у меня нет. Желающие в справедливости неравенства (1) могут его проверить на своих примерах.

Вывод


Рассмотрена реализация на Python метода определения авторства текстов по частоте употребления новых слов. Приведена формула для сравнительного анализа трёх текстов два из которых одного автора, а третий другого. Приведен пример для сравнительного анализа произведений Дена Броуна и Роберта Ладлэма.

Ссылки


  1. Авторство писателей можно узнать по специальной формуле.
  2. J. C. Baker A Test of Authorship Based on the Rate at which New Words Enter an Author's Text Journal Article published 1 Jan 1988 in Literary and Linguistic Computing volume 3 issue 1 on pages 36 to 39.
  3. Простая программа на Python для гиперболической аппроксимации статистических данных
  4. Законы Зипфа (Ципфа)
Поделиться с друзьями
-->

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


  1. GH0st3rs
    04.03.2017 16:35
    +13

    Реферат может быть и норм, но как статья он ни о чем. Это чисто моё мнение. Думаю стоило привести больше кода, с его описанием.
    Тема не плохая, например можно было привести пример работы этого алгоритма на анализе сообщений из соц. сетей.


    1. iXCray
      04.03.2017 18:32
      -6

      Угадаю автора сообщения с одного кек


    1. zone19
      06.03.2017 11:07

      Я думаю алгоритм для небольших сообщений не будет работать.


  1. encyclopedist
    04.03.2017 23:12
    +6

    Пожалуйста, не надо скриншоты в JPEG!


  1. ProstoTyoma
    05.03.2017 01:35

    Скоро буден нужен обфускатор для естественного языка.


    1. isden
      05.03.2017 08:57

      Есть уже, вот буквально вчера копал про grammarly и hemingway — там есть возможность коррекции структуры предложений и замены сложных слов синонимами.


  1. SomeOneWhoCares
    05.03.2017 14:31
    -4

    По моему мнению эта статья новое направление в определении авторства, нельзя называть ее рефератом и рекомендовать в качестве примера — использовать отзывы в социальных сетях. (это далеко не Дэн Броун)


  1. LingvoLena
    05.03.2017 15:37
    -4

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


    1. Scorobey
      05.03.2017 15:39
      -4

      Хорошо отвечу вам. Я не люблю похвал. Но для Хабра мне ни чего не жалко.


  1. schetilin
    06.03.2017 10:42
    -2

    По теме могу посоветовать:
    Серия книг «Знак вопроса» №11 1991 г. «Другому как понять тебя?»

    Знаете ли вы, что примерно половина дошедшего до нас литературного наследия анонимна? А не задумывались ли, что, изучая текст, можно не только установить автора, но и получить его психологический портрет?.

    http://www.rulit.me/series/znak-voprosa/drugomu-kak-ponyat-tebya-download-free-252162.html


  1. 3dcryx
    06.03.2017 14:09
    -3

    Скажите, можете ли вы адоптировать эту программу для русского языка и прогнать различные части «Тихого Дона»?


    1. Scorobey
      06.03.2017 14:14
      -2

      Да это не сложно. Если Вам это интересно могу опубликовать дополнение с применением pymorphy2.Сообщите какие части нужно сравнивать я приведу в качестве примера.


      1. 3dcryx
        06.03.2017 16:17
        +1

        Не то чутка сказал.
        Хотелосьбы взять любой рассказ отсюда и например первый том «Тихого Дона» и посмотреть какой вердикт выдаст программа.


    1. YourChief
      06.03.2017 20:48
      +1

      Для минусующих, кто литературой не интересуется, поясню, что идея это весьма здравая, так как сомнения в авторстве «Тихого Дона» Шолоховым весьма обоснованы.


      1. zooks
        06.03.2017 22:44
        -1

        Для начала нужно протестировать корректность работы программы на других классиках. А затем уже можно будет смело развеять «сомнения» среди всяких умников.


        1. Scorobey
          07.03.2017 00:17
          +1

          Я не помещаю не проверенных программ. Более 40 троек различных авторов показали устойчивое определение по предложному алгоритму. Вот пример Tolkien J.
          The Lord of the Rings (1995) Tolkien J
          The Lord of the Ring 1 — The Fellowship of the Ring(1954)
          Вот результат
          Factor --a 426.648 Factor--b 9584.508 Mistake of approximation-- 0.086%
          In total of words (Text-1) --265287. New words --15214. Percen new words-- 6
          Factor --a 165.307 Factor--b 3358.964 Mistake of approximation-- 0.0833%
          In total of words (Text-2) --90121. New words --6713. Percent new words-- 7
          Factor --a 26.325 Factor--b 644.835 Mistake of approximation-- 0.0906%
          In total of words (Text-3) --13754. New words --2712. Percent new words-- 20
          Average distances between art products of the author K--435.85
          Average distance between art products of the authors K and M--650.913
          При желании проверите сами.


  1. Scorobey
    07.03.2017 00:43

    Для анализа русскоязычных авторов достаточно строку stemmer = SnowballStemmer('english') заменить на строку stemmer = SnowballStemmer('russian') а вместо stop_words= nltk.corpus.stopwords.words('english') записать русские стоп слова например из. Стоп- символы русского языка http://www.algorithmist.ru/2010/12/stop-symbols-in-russian.html. stop_words=['-', 'еще', 'него', 'сказать', 'а', 'ж', 'нее', 'со', 'без', 'же', 'ней', 'совсем',
    'более', 'жизнь', 'нельзя', 'так', 'больше', 'за', 'нет', 'такой', 'будет', 'зачем', 'ни',
    'там', 'будто', 'здесь', 'нибудь', 'тебя', 'бы', 'и', 'никогда', 'тем', 'был', 'из', 'ним',
    'теперь', 'была', 'из-за', 'них', 'то', 'были', 'или', 'ничего', 'тогда', 'было', 'им', 'но',
    'того', 'быть', 'иногда', 'ну', 'тоже', 'в', 'их', 'о', 'только', 'вам', 'к', 'об', 'том', 'вас',
    'кажется', 'один', 'тот', 'вдруг', 'как', 'он', 'три', 'ведь', 'какая', 'она', 'тут', 'во', 'какой',
    'они', 'ты', 'вот', 'когда', 'опять', 'у', 'впрочем', 'конечно', 'от', 'уж', 'все', 'которого',
    'перед', 'уже', 'всегда', 'которые', 'по', 'хорошо', 'всего', 'кто', 'под', 'хоть', 'всех',
    'куда', 'после', 'чего', 'всю', 'ли', 'потом', 'человек', 'вы', 'лучше', 'потому', 'чем', 'г',
    'между', 'почти', 'через', 'где', 'меня', 'при', 'что', '\nговорил', 'мне', 'про', 'чтоб', 'да',
    'много', 'раз', 'чтобы', 'даже', 'может', 'разве', 'чуть', 'два', 'можно', 'с', 'эти', 'для',
    'мой', 'сам', 'этого', 'до', 'моя', 'свое', 'этой', 'другой', 'мы', 'свою', 'этом', 'его', 'на',
    'себе', 'этот', 'ее', 'над', 'себя', 'эту', 'ей', 'надо', 'сегодня', 'я', 'ему', 'наконец', 'сейчас',
    'если', 'нас', 'сказал', 'есть', 'не', 'сказала']


    1. bopoh13
      07.03.2017 11:47

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


  1. Scorobey
    07.03.2017 16:17

    Я использовал stop_words= nltk.corpus.stopwords.words('english') с корпуса официального корпуса Brown.На русские стоп слова я дал ссылку http://www.algorithmist.ru/2010/12/stop-symbols-in-russian.html. Из которой они переписаны как вариант для использования. Если ссылка Вас не устраивает создайте собственный собственный список стоп-слов. Замечание не по адресу.