Эта статья является совместной статьей Армин Бехджати и Бахрам Мохаммадпур

Этот проект был выполнен в марте 2018 года.

Сканер комментариев Zoodfood:

сканирование комментариев от zoodfood.

Сначала мы открываем страницу со списком ресторанов, затем анализируем извлеченные ссылки на рестораны, на каждой странице 12 ресторанов. мы определяем функцию «get_restaurants_list», чтобы получить список ресторанов для каждой страницы с учетом номера страницы.

Список ресторанов zoodfood состоит из 288 страниц, поэтому мы получаем данные для каждой страницы.
Мы можем уменьшить время выполнения, используя потоки.

мы записываем ссылки ресторанов в текстовый файл, чтобы мы могли использовать их позже

чтение ссылок из текстового файла:

пример ссылки: ‘/ restaurant / menu / 37j82x / kenzo / fereshteh’

нам нужен 3-й аргумент этого URL-адреса, который называется именем поставщика. Это идентификатор ресторана в snappfood API.

нам просто нужно имя поставщика для сбора комментариев.

мы храним названия поставщиков в "restaurant_vendor_name"

URL комментария API:

https://www.zoodfood.com/restaurant/comment/vendor/{vendor_id}/{page}
в каждом вызове API мы получаем 10 комментариев, а следующая страница получит 10 следующих комментариев
, если мы запросим этот URL: https://www.zoodfood.com/restaurant/comment/vendor/37j82x/0

мы получим что-то вроде этого:

{«Status»: true, «data»: {«count»: 435, «pageSize»: 10, «comments»: […]}}

«count» показывает количество комментариев.
мы должны сделать (count / 10) вызовов API, чтобы получить все комментарии.

Функция «get_comments_for_restaurant_page» возвращает данные комментария с учетом «vendor_name» и «номера страницы».

нам нужна функция, чтобы выполнить всю работу. Чтобы упростить процесс, мы определяем функцию ниже, но сначала мы должны подключиться к mongoDB.

получить все комментарии

нам нужен текстовый файл, содержащий все тексты комментариев.

Языковая модель:

Мы хотим сделать классификатор, чтобы прогнозировать эмоции от комментариев ресторана.

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

указание PATH:
PATH_lang: языковая модель PATH
PATH: помеченные данные для анализа настроений PATH

Указание пути обучения и проверки как для языковой модели, так и для помеченных данных:
TRN: путь для обучения помеченных данных
VAL = путь для проверки помеченных данных
TRN_lang: путь к обучающим данным языковой модели
VAL_lang = путь к данным проверки языковой модели

создание папок обучения и проверки, содержащих файлы обучения и проверки языковой модели.

подсчет слов в наборе данных поезда и проверки:

2120494
791984

Токенизация текста:
прежде чем мы сможем работать с текстом, мы должны сначала преобразовать его в массив токенов (или слов).
для токенизации текста мы используем токенизатор с открытым исходным кодом «spacy», который поддерживает персидский язык тоже. хотя персидский токенизатор не очень хорош, его достаточно для этого проекта, хотя он требует некоторых улучшений.

'سس اسپرینگ رول اشتباه ارسال شده بود'

проверка токенизатора на один комментарий из набора данных.
каждый токен разделяется знаком «?» отметка.
вроде все работает нормально.

'میتونم?بگم?هیچ?ارزونی?ای?بی?علت?نیست?.?کیفیت?پایین?ولی?با?توجه?به?مثل?هر?چقدر?پول?بدی?اش?میخوری?میشه?گفت?قابل?قبول?ولی?پیتزا?پدر?خوب?نارمک?تویه?همین?رنج?قیمت?کیفیت?بهتری?داره'

мы используем библиотеку fastai, которая работает с torchtext. поэтому мы должны создать поле torchtext, чтобы передать его объекту LnguageModelData.
здесь мы рассказываем, как предварительно обработать текст. просто сделав это строчными буквами и используя пространство для токенизации.

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

после построения ModelData объект ModelData заполняет атрибуты объекта TEXT.

(491, 7955, 1, 2364421)

первые двенадцать элементов карты от целых чисел до уникальных токенов:

['<unk>',
 '<pad>',
 'بود',
 'و',
 'غذا',
 'خوب',
 'از',
 'به',
 'خیلی',
 'هم',
 'عالی',
 'که']

числовое преобразование - один из атрибутов ТЕКСТА, который обрабатывает преобразование токенов в целые числа в тексте.

Variable containing:
  170
    7
  347
    0
  537
   17
  134
  454
 1869
    7
  491
    0
[torch.cuda.LongTensor of size 12x1 (GPU 0)]

объект LanguageModelData создает пакеты из 64 столбцов (это наш размер пакета) и длины последовательности около 75 токенов (это bptt, который мы определили)
Каждый пакет также содержит те же данные, что и ярлыки, но на одно слово позже в тексте так как мы стараемся всегда предугадывать следующее слово. Метки сведены в одномерный массив.
поскольку мы не можем перемешивать текстовые файлы, torchtext автоматически немного изменяет значение bptt, чтобы добавить элемент случайности.

(Variable containing:
   170    41     5  ...      2   308   247
     7    98     2  ...     26     3    29
   347    30     3  ...     42    21   279
        ...          ⋱          ...       
     5  2712     2  ...      3   373   163
     2    37    18  ...     74  3290    51
    18  2449   451  ...    109  1155   112
 [torch.cuda.LongTensor of size 73x64 (GPU 0)], Variable containing:
     7
    98
     2
   ⋮  
    75
    48
     0
 [torch.cuda.LongTensor of size 4672 (GPU 0)])

em_sz: размер вектора внедрения
nh: количество активаций в каждом слое
nl: количество слоев

функция оптимизатора
значение импульса 0,7 работает лучше всего, поэтому мы не используем значение по умолчанию 0,9.

fastai использует вариант современной языковой модели AWD LSTM, разработанной Стивеном Мерити. Так что эту модель мы тоже используем.

немного тренируем модель:

HBox(children=(IntProgress(value=0, description='Epoch', max=75), HTML(value='')))
epoch      trn_loss   val_loss                              
    0      6.263493   6.211119  
    1      5.307442   5.09662                               
    2      5.006752   4.829635                              
    3      4.864222   4.715991                              
    4      4.826177   4.692709                              
    5      4.64845    4.495593                              
    6      4.478897   4.357899                              
    7      4.363075   4.269142                              
    8      4.283838   4.214092                              
    9      4.214998   4.175522                              
    10     4.162878   4.152645                              
    11     4.130756   4.13245                               
    12     4.104955   4.122128                              
    13     4.100972   4.117318                              
    14     4.087452   4.115951                              
    15     4.19065    4.151838                              
    16     4.134897   4.129659                              
    17     4.121771   4.120149                              
    18     4.071009   4.110334                              
    19     4.039296   4.102594                              
    20     4.021478   4.095991                              
    21     3.978974   4.087306                              
    22     3.95643    4.079997                              
    23     3.939815   4.078523                              
    24     3.937055   4.074559                              
    25     3.900932   4.069588                              
    26     3.850793   4.075124                              
    27     3.855999   4.065688                              
    28     3.80646    4.072929                              
    29     3.809924   4.069959                              
    30     3.80369    4.067943                              
    31     3.812806   4.067925                              
    32     3.807241   4.067443                              
    33     3.768194   4.069095                              
    34     3.761686   4.070869                              
    35     3.954122   4.091923                              
    36     3.935312   4.091307                              
    37     3.938833   4.092941                              
    38     3.918598   4.088365                              
    39     3.897253   4.091039                              
    40     3.876273   4.094545                              
    41     3.86413    4.096863                              
    42     3.863323   4.088464                              
    43     3.841176   4.09819                               
    44     3.870419   4.084446                              
    45     3.831362   4.09162                               
    46     3.804627   4.102284                              
    47     3.808969   4.085278                              
    48     3.805639   4.087205                              
    49     3.777925   4.095012                              
    50     3.751137   4.1057                                
    51     3.761073   4.0914                                
    52     3.71945    4.108792                              
    53     3.705185   4.110999                              
    54     3.69791    4.110427                              
    55     3.691067   4.108355                              
    56     3.672802   4.113387                              
    57     3.68202    4.103521                              
    58     3.649078   4.115421                              
    59     3.676602   4.09705                               
    60     3.630621   4.114202                              
    61     3.613245   4.121602                              
    62     3.615716   4.118817                              
    63     3.629888   4.109546                              
    64     3.601175   4.118355                              
    65     3.578798   4.127409                              
    66     3.569921   4.126852                              
    67     3.564669   4.127878                              
    68     3.569504   4.126769                              
    69     3.558655   4.127853                              
    70     3.573381   4.126194                              
    71     3.559762   4.128838                              
    72     3.572878   4.128811                              
    73     3.578699   4.130381                              
    74     3.545339   4.130868
[4.130867616921622]

Сохраняем вложения для дальнейшего использования.

Давайте протестируем языковую модель, чтобы увидеть, как она работает:

['<unk>', 'بود', 'و', 'عالی', 'خوب', 'با', 'هم', 'که', 'به', 'خیلی']

Вроде нормально работает!

کباب <unk> خیلی خوشمزه و خوب بود. فقط ای کاش <unk> که تو منو زده بودن با چیزی ک ارسال شد ...

Анализ настроений:

Здесь мы определяем наш набор данных fastai / torchtext:

sequencetial = False означает, что текст должен быть сначала токенизирован.
splits - это метод torchtext, который создает наборы для обучения, тестирования и проверки.

используя fastai, мы можем создать объект ModelData из разделов torchtext.

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

HBox(children=(IntProgress(value=0, description='Epoch', max=5), HTML(value='')))
epoch      trn_loss   val_loss   accuracy                       
    0      0.914599   1.026246   0.526914  
    1      0.892305   1.073445   0.526914                       
    2      0.890372   1.029869   0.526914                       
    3      0.895171   1.018384   0.526914                       
    4      0.907669   1.034427   0.526914
HBox(children=(IntProgress(value=0, description='Epoch', max=25), HTML(value='')))
epoch      trn_loss   val_loss   accuracy                      
    0      0.726858   0.807458   0.658791  
    1      0.691951   0.799014   0.674747                      
    2      0.672657   0.861043   0.665392                      
    3      0.666511   0.858039   0.677368                      
    4      0.659266   0.843153   0.678958                      
    5      0.687026   0.764765   0.669744                      
    6      0.6328     0.80844    0.670203                      
    7      0.643107   0.885304   0.672158                      
    8      0.625191   0.980532   0.674329                      
    9      0.627007   0.818966   0.679019                      
    10     0.662649   0.773294   0.658341                      
    11     0.651018   0.732899   0.693246                      
    12     0.640039   0.774128   0.681997                      
    13     0.646645   0.818812   0.685979                      
    14     0.629662   0.818131   0.687009                      
    15     0.627583   1.013715   0.684953                      
    16     0.620577   0.789786   0.691546                      
    17     0.621732   0.755267   0.689668                      
    18     0.616339   0.812259   0.69037                       
    19     0.628711   0.816256   0.685763                      
    20     0.631954   0.869854   0.663502                      
    21     0.648067   0.792397   0.689935                      
    22     0.621395   0.811201   0.687528                      
    23     0.627996   0.75971    0.692931                      
    24     0.61478    0.766722   0.694669
[0.7667221994412634, 0.6946690829240649]

Точность :

0.7319195114773396
HBox(children=(IntProgress(value=0, description='Epoch', max=5), HTML(value='')))
epoch      trn_loss   val_loss   accuracy                       
    0      0.605273   0.795732   0.697832  
    1      0.605745   0.737048   0.701651                       
    2      0.61152    0.726605   0.705618                       
    3      0.618649   0.898131   0.680639                       
    4      0.607915   0.835565   0.684423
HBox(children=(IntProgress(value=0, description='Epoch', max=25), HTML(value='')))
epoch      trn_loss   val_loss   accuracy                      
    0      0.63425    0.712354   0.70744   
    1      0.625679   0.7335     0.696126                      
    2      0.598707   0.762889   0.694836                      
    3      0.618014   0.803139   0.694313                      
    4      0.592371   0.827738   0.683457                      
    5      0.593831   0.758763   0.684881                      
    6      0.612648   0.803343   0.663893                      
    7      0.613446   0.759131   0.694913                      
    8      0.590957   0.866204   0.691297                      
    9      0.59238    1.015298   0.688887                      
    10     0.631985   0.876454   0.65384                       
    11     0.610506   0.83315    0.689219                      
    12     0.609516   0.753415   0.695011                      
    13     0.612919   0.785118   0.691572                      
    14     0.59885    0.770415   0.695097                      
    15     0.59031    0.845301   0.677381                      
    16     0.616533   0.770404   0.684773                      
    17     0.60326    0.84417    0.691907                      
    18     0.587279   0.800148   0.688964                      
    19     0.611245   0.831045   0.689919                      
    20     0.604469   0.737693   0.707982                      
    21     0.594355   0.855759   0.676296                      
    22     0.600001   0.890678   0.679592                      
    23     0.578646   0.789512   0.691539                      
    24     0.606092   0.871126   0.687559
[0.8711255853035156, 0.6875590290895354]
HBox(children=(IntProgress(value=0, description='Epoch', max=1), HTML(value='')))
61%|██████    | 1335/2188 [00:40<00:25, 33.37it/s, loss=2.29]