форкнуто от main/is_dnn
Вы не можете выбрать более 25 тем
Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
337 строки
18 KiB
Markdown
337 строки
18 KiB
Markdown
# Лабораторная работа №4: Распознование последовательностей
|
|
**Ватьков А..С., Харисов С.Р. — А-01-22**
|
|
## Вариант 2
|
|
|
|
### Цель работы
|
|
Получить практические навыки обработки текстовой информации с помощьюрекуррентныхискусственных нейронных сетей при решении задачи определения тональности текста.
|
|
|
|
---
|
|
|
|
### 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=7,
|
|
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["<PAD>"] = 0
|
|
word_to_id["<START>"] = 1
|
|
word_to_id["<UNK>"] = 2
|
|
word_to_id["<UNUSED>"] = 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))
|
|
```
|
|
**Результат выполнения:**
|
|
```
|
|
<START> the bad out takes from <UNK> of fire <UNK> together without any real story br br dean <UNK> tries to be a real actor and fails again br br in the end the <UNK> quit in <UNK> br br <UNK>
|
|
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))
|
|
```
|
|
|
|
**Результат выполнения:**
|
|
```
|
|
<PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <START> the bad out takes from <UNK> of fire <UNK> together without any real story br br dean <UNK> tries to be a real actor and fails again br br in the end the <UNK> quit in <UNK> br br <UNK>
|
|
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))
|
|
```
|
|
|
|
**Результат выполнения:**
|
|

|
|
```
|
|
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) говорит о высокой способности модели различать два класса (положительные и отрицательные отзывы)
|
|
|
|
|
|
|
|
|