Advertisement
Guest User

Untitled

a guest
Dec 16th, 2018
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.27 KB | None | 0 0
  1. # Лабораторная работа №4
  2.  
  3. ## Дано
  4.  
  5. 1. Набор заданных английских текстов большого размера.
  6. Набор таких файлов можно скачать и положить в папку `lab_4`:
  7.  
  8. * [5_7.txt](https://www.dropbox.com/s/ch486h1avdjaifg/5_7.txt?dl=1)
  9. * [15_2.txt](https://www.dropbox.com/s/kkz12uriw6gj6qx/15_2.txt?dl=1)
  10. * [10547_3.txt](https://www.dropbox.com/s/75yzydzwxgud1j1/10547_3.txt?dl=1)
  11. * [12230_7.txt](https://www.dropbox.com/s/tzm7iylvkptw1kr/12230_7.txt?dl=1)
  12.  
  13. Таким образом, повторить структуру:
  14.  
  15. ```bash
  16. |-- 2018-2-level-labs
  17. |-- lab_4
  18. |-- 5_7.txt
  19. |-- 15_2.txt
  20. |-- 10547_3.txt
  21. |-- 12230_7.txt
  22. ```
  23.  
  24. Каждый текст - это отдельный текстовый файл.
  25.  
  26. Если интересно, то весь набор текстов можно скачать
  27. [по ссылке](http://ai.stanford.edu/~amaas/data/sentiment/).
  28.  
  29. ## Что надо сделать
  30.  
  31. ### Шаг 0.1 Подготовка (проделать вместе с преподавателем на практике)
  32.  
  33. 1. В имеющемся форке репозитория, обновить содержимое до последнего доступного
  34. состояния в родительском репозитории.
  35. 2. Изменить файл `main.py`
  36. 3. Закоммитить изменения и создать pull request
  37.  
  38. ### Шаг 0.2 Прочитать содержимое документов
  39.  
  40. Необходимо считать все документы в список из строк.
  41.  
  42. > **Внимание**: этот код уже написан в `main.py`. Если у вас больше файлов, убедитесь, что
  43. > все файлы указаны в этом списке.
  44.  
  45. ### Шаг 1. Подготовка корпуса к использованию
  46.  
  47. Требуется сделать очистку текста от ненужных символов и знаков пунктуации
  48. и токенизацию (разбиение на слова).
  49.  
  50. Для этого реализуем метод `clean_tokenize_corpus(texts) -> list`:
  51.  
  52. ```python
  53. def clean_tokenize_corpus(texts):
  54. pass
  55. ```
  56.  
  57. Метод возвращает список из текстов, каждый из которых - список токенов (слов).
  58.  
  59. Например, есть два текста:
  60.  
  61. 1. `Mar#y wa$nted, to swim! However, she was afraid of sharks.`
  62. 2. `The film concerns a genetically engineered snake`.
  63.  
  64. Из них должен получиться следующий список:
  65.  
  66. ```json
  67. [
  68. [
  69. "mary", "wanted", "to", "swim", "however", "she", "was", "afraid", "of", "sharks"
  70. ],
  71. [
  72. "the", "file", "concerns", "a", "genetically", "engineered", "snake"
  73. ]
  74. ]
  75. ```
  76.  
  77. ## Шаг 2. Создание класса расчета TF-IDF
  78.  
  79. ### Шаг 2.1 Объявление полей класса
  80.  
  81. Создаем класс `TfIdfCalculator`. Внутри него задаем поля `corpus`, `tf_values`, `idf_values`, `tf_idf_values`.
  82.  
  83. ### Шаг 2.2 Заполнение класса
  84.  
  85. Класс `TfIdfCalculator` имеет конструктор, принимающий на вход корпус, то есть
  86. список из строк и сохраняющий этот корпус во внутреннее поле класса `corpus`.
  87.  
  88. ### Шаг 2.3 Расчет TF
  89.  
  90. Итак, для каждого слова из каждого документа нужно уметь рассчитать TF-IDF показатель.
  91.  
  92. А именно, он состоит из двух частей. Первая часть - это TF (term frequency) - обычная частота
  93. слова в рамках заданного документа. Формула расчета такова:
  94. <img src="https://latex.codecogs.com/gif.latex?tf(t,d)&space;=&space;\frac{n_{t}}{\sum_{k}{n_{k}}}" title="tf(t,d) = \frac{n_{t}}{\sum_{k}{n_{k}}}" />
  95.  
  96. Здесь <img src="https://latex.codecogs.com/gif.latex?n_{t}" title="n_{t}" />
  97. это количество раз слово <img src="https://latex.codecogs.com/gif.latex?t" title="t" />
  98. встречается в документе <img src="https://latex.codecogs.com/gif.latex?d" title="d" />.
  99.  
  100. **TF** тем больше чем чаще слово встречается в заданном документе и тем меньше чем реже
  101. встречается заданное слово. Таким образом, мы получаем важность слова в данном тексте.
  102.  
  103. Внутри класса необходимо реализовать метод `calculate_tf(self)`:
  104.  
  105. ```python
  106. class TfIdfCalculator:
  107. ...
  108. def calculate_tf(self):
  109. pass
  110. ```
  111.  
  112. Данный метод для каждого текста из корпуса, который уже хранится в классе,
  113. рассчитывает значение **TF** для каждого слова в этом документе. В результате, для
  114. одного текста получается словарь, который содержит структуру:
  115.  
  116. ```json
  117. {
  118. "word1": 0.17,
  119. "word2": 0.45
  120. }
  121. ```
  122.  
  123. А так как таких текстов у нас
  124. <img src="https://latex.codecogs.com/gif.latex?|D|" title="|D|" />, то и
  125. в результате работы функции получается список из
  126. <img src="https://latex.codecogs.com/gif.latex?|D|" title="|D|" /> элементов.
  127.  
  128. Каждый элемент списка - словарь с **TF** для каждого слова.
  129.  
  130. Полученный список метод `calculate_tf(self)` сохраняет в собственное поле
  131. `self.tf_values`.
  132.  
  133. Обратите внимание, вам требуется найти частоту слова в данном тексте, что посчитать
  134. значение **TF** для этого слова.
  135. Вы это уже делали в первой лабораторной работе, однако, теперь текст - это не
  136. единая строка, а массив из строк, вспомните и сделайте аналогично, слегка
  137. переработав.
  138.  
  139. ### Шаг 2.4 Расчет IDF
  140.  
  141. Вторая часть - это IDF (inversed document frequency):
  142. <img src="https://latex.codecogs.com/gif.latex?idf(t,D)&space;=&space;log(\frac{|D|}{|\{d_{i}&space;\epsilon&space;D&space;|&space;t&space;\epsilon&space;d_{i}\}|})" title="idf(t,D) = log(\frac{|D|}{|\{d_{i} \epsilon D | t \epsilon d_{i}\}|})" />
  143.  
  144. **IDF** тем больше чем реже слово встречается в корпусе и тем меньше чем чаще
  145. встречается заданное слово.
  146.  
  147. Здесь: <img src="https://latex.codecogs.com/gif.latex?|D|" title="|D|" /> - это
  148. количество документов в корпусе, а
  149. <img src="https://latex.codecogs.com/gif.latex?|\{d_{i}&space;\epsilon&space;D&space;|&space;t&space;\epsilon&space;d_{i}\}|" title="|\{d_{i} \epsilon D | t \epsilon d_{i}\}|" />
  150. - это количество документов, в которых присутствовало слово
  151. <img src="https://latex.codecogs.com/gif.latex?t" title="t" />.
  152.  
  153. Внутри класса необходимо реализовать метод `calculate_idf(self)`:
  154.  
  155. ```python
  156. class TfIdfCalculator:
  157. ...
  158. def calculate_idf(self):
  159. pass
  160. ```
  161.  
  162. Данный метод для каждого текста из корпуса, который уже хранится в классе,
  163. рассчитывает значение **IDF** для каждого слова, которое встречается хотя бы в одном
  164. документе. В результате, получается словарь, который содержит структуру:
  165.  
  166. ```json
  167. {
  168. "word1": 0.33,
  169. "word2": 0.21
  170. }
  171. ```
  172.  
  173. Ключ - слово, значение - **IDF** для данного слова.
  174.  
  175. Полученный список метод `calculate_idf(self)` сохраняет в собственное поле
  176. `self.idf_values`.
  177.  
  178. ### Шаг 2.5 Расчет TF-IDF
  179.  
  180. Теперь можем рассчитать общую метрику **TF-IDF**:
  181. <img src="https://latex.codecogs.com/gif.latex?\operatorname&space;{tf-idf}(t,d,D)=\operatorname&space;{tf}(t,d)\times&space;\operatorname&space;{idf}(t,D)" title="\operatorname {tf-idf}(t,d,D)=\operatorname {tf}(t,d)\times \operatorname {idf}(t,D)" />
  182.  
  183. Внутри класса необходимо реализовать метод `calculate(self)`:
  184.  
  185. ```python
  186. class TfIdfCalculator:
  187. ...
  188. def calculate(self):
  189. pass
  190. ```
  191.  
  192. Данный метод для каждого текста из корпуса, который уже хранится в классе,
  193. рассчитывает значение **TF-IDF** для каждого слова, которое встречается хотя бы в одном
  194. документе. В результате, получается словарь, который содержит структуру:
  195.  
  196. ```json
  197. {
  198. "word1": 0.33,
  199. "word2": 0.21
  200. }
  201. ```
  202.  
  203. Ключ - слово, значение - **TF-IDF** для данного слова.
  204.  
  205. Полученный список метод `calculate(self)` сохраняет в собственное поле
  206. `self.tf_idf_values`.
  207.  
  208. Если значений `self.tf_values`, `self.idf_values` нет или они пусты,
  209. метод ничего не делает.
  210.  
  211. ### Шаг 2.6 Получение отчета для данного слова
  212.  
  213. Теперь, когда были произведены расчеты **TF-IDF** для каждого слова, мы можем начать
  214. анализировать результаты, например, сравнивать значения метрики для нескольких слов.
  215.  
  216. Чтобы узнать информацию по выбранному слову, требуется реализовать метод
  217. `report_on_word(self, word)`:
  218.  
  219. ```python
  220. class TfIdfCalculator:
  221. ...
  222. def report_on_word(self, word, document_index):
  223. pass
  224. ```
  225.  
  226. Данный метод возвращает значение кортеж, где первый элемент - это **TF-IDF** для
  227. заданного слова, если оно встречалось в тексте и `None` иначе, второе - место,
  228. которое данное слово занимает в рейтинге значимости слов в заданном тексте.
  229.  
  230. Например, получаем кортеж (1.3, 100).
  231. Это означает, что слово имеет значение **TF-IDF** равное 1.3, является сотым
  232. по значимости в тексте. Важно при определении места учитывать тот факт, что на
  233. одном месте в рейтинге могут быть сразу несколько слов.
  234.  
  235. В таком рейтинге, первое место у самого значимого слова, то есть у того, чьё значение
  236. **TF-IDF** максимально.
  237.  
  238. ### Шаг 2.7 Сохранение отчета в Excel-приемлемом формате
  239.  
  240. > **Важно:** выполнение заданий 1, 2.1-2.6 + 2.7 соответствует оценке 9 баллов.
  241.  
  242. Требуется сохранить содержимое наших расчетов в `.csv` файл. Особенность такого файла
  243. заключается в том, что все строки - это наборы значений, разделенных запятой.
  244.  
  245. Например, есть таблица:
  246.  
  247. | Слово | TF (text_1) | TF (text_1) | IDF | TF-IDF (text_1) | TF-IDF (text_2) |
  248. | ------------- |-------------| -----| -----| -----| -----|
  249. | bag | 0.142 | 0 | 0.3 | 0.043 | 0 |
  250.  
  251. Превращается в текстовый файл (**не бинарный**) `.csv`, с содержимым:
  252.  
  253. ```sh
  254. word,tf_text_1,tf_text_2,idf,tf_idf_text_1,tf_idf_text_2
  255. bag,0.142,0,0.3,0.043,0
  256. ```
  257.  
  258. Вам необходимо обеспечить сохранение в такой файл расчетов по заданному корпусу.
  259.  
  260. Для этого, требуется реализовать метод `dump_report_csv(self)`:
  261.  
  262. ```python
  263. class TfIdfCalculator:
  264. ...
  265. def dump_report_csv(self):
  266. pass
  267. ```
  268.  
  269. Этот метод создает файл `report.csv` в той же директории, что и сам `main.py` для
  270. Лабораторной работы №4. Если расчеты не производились, то создается пустой файл
  271. (без строк).
  272.  
  273. Проверить вы себя сможете легко, для этого можно открыть Excel и импортировать данные
  274. из `.csv` файла -
  275. [инструкция](http://office-guru.ru/excel/preobrazovyvaem-csv-v-excel-kak-importirovat-faily-csv-v-elektronnye-tablicy-excel-368.html#csv1-3).
  276.  
  277. Обратите внимание на то, что первой строкой идет заголовок таблицы, он должен
  278. соответствовать количеству колонок.
  279.  
  280. В названии колонок вместо
  281. `_text_1` нужно вставить название файла, которому соответствует данная колонка.
  282. Для этого, вам нужно расширить конструктор класса списком имён файлов и сохранить
  283. его в собственном поле `file_names`.
  284.  
  285. > **Важно:** Порядок в списке имён должен соответствовать
  286. > порядку текстов в корпусе
  287.  
  288. ### Шаг 2.8 Расчет расстояния между представлениями текстов
  289.  
  290. > **Важно:** выполнение заданий 1, 2.1-2.7 + 2.8 соответствует оценке 10 баллов.
  291.  
  292. Итак, пусть у нас есть посчитанные значения **TF-IDF** для каждого слова.
  293. Кроме того, нам известны все слова из данного корпуса.
  294.  
  295. Попробуем найти "расстояние" между двумя текстами.
  296. Идея такая, что тексты на одну и ту же тему должны быть "ближе", чем тексты
  297. на разные темы. Если говорить технически, то если бы мы могли представить тексты
  298. как векторы, то расстояние между векторами для текстов одной темы были бы меньше
  299. чем расстояние между векторами для текстов разных тем.
  300.  
  301. Такой подход (превращение текстов в векторы) используется при работе нейронных сетей.
  302. Попробуем сделать первый шаг и представить наши тексты как векторы и посчитать расстояние между ними.
  303.  
  304. Для этого:
  305.  
  306. 1. Есть два текста:
  307. `["mary", "was", "angry", "with", "tom"]` и `["tom", "liked", "mary"]`.
  308. Возьмем список все слов. Именно список, так как нам впоследствии будет важен
  309. порядок.
  310. Например: `words=['mary', 'was', 'angry', 'with', 'tom', 'liked']`.
  311. 2. Теперь представим тексты как векторы, где на позиции `i` будет стоять либо
  312. значение **TF-IDF**, если `words[i]` есть в тексте либо 0.
  313. Получаем, для первого слова: `[0.1, 0.2, 0.3, 0.4, 0.5, 0]`, а для второго:
  314. `[0.12, 0, 0, 0, 0.13, 0.17]`. Числа, конечно, вымышленные.
  315. 3. Найдем косинусное расстояние между векторами: <img src="https://latex.codecogs.com/gif.latex?cos(A,B)&space;=&space;\frac{A&space;\cdot&space;B}{||A||||B||}&space;=&space;\frac{\sum_{i=1}^{n}A_i&space;\times&space;B_i}{\sqrt{\sum_{i=1}^{n}{(A_i)^{2}}}&space;\times&space;\sqrt{\sum_{i=1}^{n}{(B_i)^2}}}" title="cos(A,B) = \frac{A \cdot B}{||A||||B||} = \frac{\sum_{i=1}^{n}A_i \times B_i}{\sqrt{\sum_{i=1}^{n}{(A_i)^{2}}} \times \sqrt{\sum_{i=1}^{n}{(B_i)^2}}}" />
  316.  
  317. Для этого, требуется реализовать метод
  318. `cosine_distance(self, index_text_1, index_text_2)`:
  319.  
  320. ```python
  321. class TfIdfCalculator:
  322. ...
  323. def cosine_distance(self, index_text_1, index_text_2):
  324. pass
  325. ```
  326.  
  327. Этот метод создает принимает на вход индексы двух текстов в корпусе, который мы
  328. использовали для инициализации экземпляра класса. Он должен возвращать значение
  329. расстояния двух векторов. В случае несуществования такого/таких индексов возвращается
  330. очень большое число - `1000`.
  331.  
  332. ## Ссылки
  333.  
  334. В данной работе предполагается использовать избранные тексты из
  335.  
  336. ```sh
  337. @InProceedings{maas-EtAl:2011:ACL-HLT2011,
  338. author = {Maas, Andrew L. and Daly, Raymond E. and Pham, Peter T. and Huang, Dan and Ng, Andrew Y. and Potts, Christopher},
  339. title = {Learning Word Vectors for Sentiment Analysis},
  340. booktitle = {Proceedings of the 49th Annual Meeting of the Association for Computational Linguistics: Human Language Technologies},
  341. month = {June},
  342. year = {2011},
  343. address = {Portland, Oregon, USA},
  344. publisher = {Association for Computational Linguistics},
  345. pages = {142--150},
  346. url = {http://www.aclweb.org/anthology/P11-1015}
  347. }
  348. ```
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement