diff --git a/labworks/LW4/report.md b/labworks/LW4/report.md new file mode 100644 index 0000000..3682bfe --- /dev/null +++ b/labworks/LW4/report.md @@ -0,0 +1,339 @@ +# Лабораторная работа №4: Распознование последовательностей +**Ватьков А..С., Харисов С.Р. — А-01-22** +## Вариант 2 + +### Цель работы +Получить практические навыки обработки текстовой информации с помощьюрекуррентныхискусственных нейронных сетей при решении задачи определения тональности текста. + +--- + +## ЗАДАНИЕ 1: + +### 1) В среде Google Colab создали новый блокнот (notebook). Импортировали необходимые для работы библиотеки модули. +```python +# импорт модулей +import os +os.chdir('/content/drive/MyDrive/Colab Notebooks/is_LR4') + +from tensorflow import keras +from tensorflow.keras import layers +from tensorflow.keras.models import Sequential +import matplotlib.pyplot as plt +import numpy as np +``` + +```python +import tensorflow as tf +device_name = tf.test.gpu_device_name() +if device_name != '/device:GPU:0': + raise SystemError('GPU device not found') +print('Found GPU at: {}'.format(device_name)) +``` + +### 2) Загрузили набор данных IMDb, содержащий оцифрованные отзывы на фильмы, размеченные на два класса: позитивные и негативные. При загрузке набора данных параметр seed выбрали равным значению (4k – 1)=7, где k=2 – номер бригады. Вывели размеры полученных обучающих и тестовых массивов данных. +```python +# загрузка датасета +from keras.datasets import imdb + +vocabulary_size = 5000 +index_from = 3 + +(X_train, y_train), (X_test, y_test) = imdb.load_data( + path="imdb.npz", + num_words=vocabulary_size, + skip_top=0, + maxlen=None, + seed=26, + start_char=1, + oov_char=2, + index_from=index_from + ) + +# вывод размерностей +print('Shape of X train:', X_train.shape) +print('Shape of y train:', y_train.shape) +print('Shape of X test:', X_test.shape) +print('Shape of y test:', y_test.shape) +``` + +**Результат выполнения:** +``` +Shape of X train: (25000,) +Shape of y train: (25000,) +Shape of X test: (25000,) +Shape of y test: (25000,) +``` + +### 3) Вывели один отзыв из обучающего множества в виде списка индексов слов. Преобразовали список индексов в текст и вывели отзыв в виде текста. Вывели длину отзыва. Вывели метку класса данного отзыва и название класса (1 – Positive, 0 – Negative). + +```python +# создание словаря для перевода индексов в слова +# заргузка словаря "слово:индекс" +word_to_id = imdb.get_word_index() +# уточнение словаря +word_to_id = {key:(value + index_from) for key,value in word_to_id.items()} +word_to_id[""] = 0 +word_to_id[""] = 1 +word_to_id[""] = 2 +word_to_id[""] = 3 +# создание обратного словаря "индекс:слово" +id_to_word = {value:key for key,value in word_to_id.items()} +``` +```python +print(X_train[26]) +print('len:',len(X_train[26])) +``` + +**Результат выполнения:** +``` +[1, 4, 78, 46, 304, 39, 2, 7, 968, 2, 295, 209, 101, 147, 65, 10, 10, 2643, 2, 497, 8, 30, 6, 147, 284, 5, 996, 174, 10, 10, 11, 4, 130, 4, 2, 4979, 11, 2, 10, 10, 2] +len: 41 +``` +```python +review_as_text = ' '.join(id_to_word[id] for id in X_train[26]) +print(review_as_text) +print('len:',len(review_as_text)) +``` +**Результат выполнения:** +``` + the bad out takes from of fire together without any real story br br dean tries to be a real actor and fails again br br in the end the quit in br br +len: 193 +``` + +### 4) Вывели максимальную и минимальную длину отзыва в обучающем множестве. + +```python +print('MAX Len: ',len(max(X_train, key=len))) +print('MIN Len: ',len(min(X_train, key=len))) +``` + +**Результат выполнения:** +``` +MAX Len: 2494 +MIN Len: 11 +``` + +### 5) Провели предобработку данных. Выбрали единую длину, к которой будут приведены все отзывы. Короткие отзывы дополнили спецсимволами, а длинные обрезали до выбранной длины. + +```python +# предобработка данных +from tensorflow.keras.utils import pad_sequences +max_words = 500 +X_train = pad_sequences(X_train, maxlen=max_words, value=0, padding='pre', truncating='post') +X_test = pad_sequences(X_test, maxlen=max_words, value=0, padding='pre', truncating='post') +``` + +### 6) Повторили пункт 4. + +```python +print('MAX Len: ',len(max(X_train, key=len))) +print('MIN Len: ',len(min(X_train, key=len))) +``` + +**Результат выполнения:** +``` +MAX Len: 500 +MIN Len: 500 +``` + +### 7) Повторили пункт 3. Сделали вывод о том, как отзыв преобразовался после предобработки. + +```python +print(X_train[26]) +print('len:',len(X_train[26])) +``` + +**Результат выполнения:** +``` +[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 1 4 78 + 46 304 39 2 7 968 2 295 209 101 147 65 10 10 + 2643 2 497 8 30 6 147 284 5 996 174 10 10 11 + 4 130 4 2 4979 11 2 10 10 2] +len: 500 +``` + +```python +review_as_text = ' '.join(id_to_word[id] for id in X_train[26]) +print(review_as_text) +print('len:',len(review_as_text)) +``` + +**Результат выполнения:** +``` + the bad out takes from of fire together without any real story br br dean tries to be a real actor and fails again br br in the end the quit in br br +len: 2947 +``` +**После обработки в начало отзыва добавилось необходимое количество токенов , чтобы отзыв был длинной в 500 индексов.** + +### 8) Вывели предобработанные массивы обучающих и тестовых данных и их размерности. + +```python +# вывод данных +print('X train: \n',X_train) +print('X train: \n',X_test) + +# вывод размерностей +print('Shape of X train:', X_train.shape) +print('Shape of X test:', X_test.shape) +``` + +**Результат выполнения:** +``` +X train: + [[ 0 0 0 ... 1039 7 12] + [ 0 0 0 ... 5 2 1773] + [ 0 0 0 ... 220 175 96] + ... + [ 1 3264 153 ... 157 746 14] + [ 0 0 0 ... 3459 55 680] + [ 0 0 0 ... 14 31 56]] +X train: + [[ 0 0 0 ... 241 3366 56] + [ 0 0 0 ... 18 4 755] + [ 0 0 0 ... 149 14 20] + ... + [ 0 0 0 ... 2 2152 1835] + [ 0 0 0 ... 3768 3508 3311] + [ 0 0 0 ... 511 8 2725]] +Shape of X train: (25000, 500) +Shape of X test: (25000, 500) +``` + +### 9) Реализовали модель рекуррентной нейронной сети, состоящей из слоев Embedding, LSTM, Dropout, Dense, и обучили ее на обучающих данных с выделением части обучающих данных в качестве валидационных. Вывели информацию об архитектуре нейронной сети. Добились качества обучения по метрике accuracy не менее 0.8. + +```python +model = Sequential() +model.add(layers.Embedding(input_dim=vocabulary_size, output_dim=64, input_length=max_words, input_shape=(max_words,))) +model.add(layers.LSTM(64)) +model.add(layers.Dropout(0.45)) +model.add(layers.Dense(1, activation='sigmoid')) + +model.summary() +``` + +**Результат выполнения:** +``` +Model: "sequential_2" +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ +┃ Layer (type) ┃ Output Shape ┃ Param # ┃ +┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ +│ embedding_2 (Embedding) │ (None, 500, 64) │ 320,000 │ +├─────────────────────────────────┼────────────────────────┼───────────────┤ +│ lstm_2 (LSTM) │ (None, 64) │ 33,024 │ +├─────────────────────────────────┼────────────────────────┼───────────────┤ +│ dropout_2 (Dropout) │ (None, 64) │ 0 │ +├─────────────────────────────────┼────────────────────────┼───────────────┤ +│ dense_2 (Dense) │ (None, 1) │ 65 │ +└─────────────────────────────────┴────────────────────────┴───────────────┘ + Total params: 353,089 (1.35 MB) + Trainable params: 353,089 (1.35 MB) + Non-trainable params: 0 (0.00 B) +``` + +```python +# компилируем и обучаем модель +batch_size = 64 +epochs = 4 +model.compile(loss="binary_crossentropy", optimizer="adam", metrics=["accuracy"]) +model.fit(X_train, y_train, batch_size=batch_size, epochs=epochs, validation_split=0.1) +``` +```python +test_loss, test_acc = model.evaluate(X_test, y_test) +print(f"\nTest accuracy: {test_acc}") +``` + +**Результаты выполнения:** +``` +Test accuracy: 0.8519200086593628 +``` + +### 10) Оценили качество обучения на тестовых данных: +###- вывели значение метрики качества классификации на тестовых данных +###- вывели отчет о качестве классификации тестовой выборки +###a- построили ROC-кривую по результату обработки тестовой выборки и вычислили площадь под ROC-кривой (AUC ROC) + +```python +y_score = model.predict(X_test) +y_pred = [1 if y_score[i,0]>=0.5 else 0 for i in range(len(y_score))] + +from sklearn.metrics import classification_report +print(classification_report(y_test, y_pred, labels = [0, 1], target_names=['Negative', 'Positive'])) +``` + +**Результат выполнения:** +``` + precision recall f1-score support + + Negative 0.86 0.85 0.85 12500 + Positive 0.85 0.86 0.85 12500 + + accuracy 0.85 25000 + macro avg 0.85 0.85 0.85 25000 +weighted avg 0.85 0.85 0.85 25000 +``` + +```python +#построение ROC-кривой и AUC ROC +from sklearn.metrics import roc_curve, auc + +fpr, tpr, thresholds = roc_curve(y_test, y_score) +plt.plot(fpr, tpr) +plt.grid() +plt.xlabel('False Positive Rate') +plt.ylabel('True Positive Rate') +plt.title('ROC') +plt.show() +print('AUC ROC:', auc(fpr, tpr)) +``` + +**Результат выполнения:** +![](9punkt.png) +``` +AUC ROC: 0.9159089215999999 +``` + +### 11) Сделали выводы по результатам применения рекуррентной нейронной сети для решения задачи определения тональности текста. + +Таблица 1: +| Модель | Количество настраиваемых параметров | Количество эпох обучения | Качество классификации тестовой выборки | +|-----------------|-------------------------------------|--------------------------|-----------------------------------------| +| Рекуррентная | 353089 | 3 | accuracy:0.85 ; loss:0.5214 ; | +| | | | AUC ROC:0.9159 | + +### По результатам таблицы можно сделать вывод, что рекуррентная НС хорошо справляется с задачей определения тональности текста. Показатель accuracy = 0.85 превышает требуемый порог 0.8. Значение AUC ROC = 0.9159 (> 0.9) говорит о высокой способности модели различать два класса (положительные и отрицательные отзывы) + + + +