Аналіз настрою NacimNacim2 - OpenClassrooms

Питання ? Не хвилюйтеся, ми допоможемо вам !

inputs labels

# кодування: utf-8
імпортувати панд як pd
імпортувати numpy як np
імпортувати xml.etree.ElementTree як ET
з колекцій імпорту
імпортувати matplotlib.pyplot як plt
імпортний факел
з torch.utils.data імпортувати DataLoader, TensorDataset
імпорт факела.nn як nn

def get_list (шлях):
дерево = ET.parse (шлях)
root = tree.getroot ()
text_list = []
список думок = []
для огляду в root.findall ("Огляд"):
text_string = "

для відправленого в огляд.findall ("./ речення/речення"):
text_string = text_string + " + sent.find ("text"). text
text_string = text_string.lower ()
text_string = text_string.strip ()
text_list.append (text_string + ("\ n"))

для отримання думки в review.findall ("./ Думки/Думка"):
if (opinion.get ("category") == "LAPTOP # GENERAL"):
opinion_dict = opinion.get ("полярність")
# opinion_inner_list.append (думка_суд)
opinion_list.append (думка_суд)
повернути текстовий список, список думок

відгуки, мітки = get_list (path_train)

#test_text_list, test_opinion_list = get_list (path_test)
print ('train_text_list', відгуки)
print ()
print ('train_opinion_list', ярлики)

рядок = []
з пунктуації імпорту рядка
all_text = '' .join ([c для c у відгуках, якщо c не в розділових знаках]) # очистити розділові знаки
друк (весь_текст)

reviews_split = all_text.split ('\ n')
print ('кількість відгуків:', len (reviews_split))
all_text2 = '' .join (відгук_спліт)
words = all_text2.split ()

count_words = Лічильник (слова)
# порахувати частоту слів #
total_words = len (слова)
print (total_words) # nbr загальна кількість слів
sorted_words = count_words.most_common (total_words)
print (count_words) # & записувати частоту слів
vocab_to_int =
друк (vocab_to_int)
# створити список, який включає списки moots як цілі числа #
reviews_int = []
для огляду в reviews_split:
r = [vocab_to_int [w] для w у review.split ()]
reviews_int.append (r)
друк (reviews_int)
print ("langueuuur rev_int", len (reviews_int))

# кодувати теги #

encoded_labels = [1 if label == 'positive' else 0 if label == 'negative'else 2 if label ==' конфлікт 'else 3 для label в ярликах] #encode the label
encoded_labels = np.array (encoded_labels)

# проаналізувати дані #
reviews_len = [len (x) для x у reviews_int]
pd.Series (reviews_len) .hist ()
plt.show ()
pd.Series (reviews_len) .describe ()
# позбутися коротких і довгих значень #
print ("the labels11111", len (encoded_labels))
reviews_int = [reviews_int [i] для i, l в переліченні (reviews_len), якщо l> 0]
encoded_labels = [encoded_labels [i] для i, l в enumerate (reviews_len), якщо l> 0 і i seq_length:
new = огляд [0: seq_length]

seq_length = 395
особливості = характеристики_паду ​​(відгуки_int, довжина_довж)
друк (особливості)
len_feat = len (функції)
print ("len feat", len_feat)
split_frac = 0,8

# підготовка даних

train_x = особливості [0: int (split_frac * len_feat)] # огляди
друк ("train_x", train_x)
train_y = encoded_labels [0: int (split_frac * len_feat)] # мітки
print ("train_y", train_y)
print ("review_split", len (reviews_split))
print ("languer rev", len (reviews_int))

Залишилося # даних
preostali_x = особливості [int (split_frac * len_feat):]
preostaлий_y = закодовані_мітки [int (split_frac * len_feat):]
друк (len (залишилося_x))
друк (len (залишився_y))

# дані перевірки
valid_x = залишився_x [0: int (len (залишився_x) * 0,5)]
valid_y = залишився_y [0: int (len (залишився_y) * 0.5)]
print ('len (valid_x)', len (valid_x))
print ('len (valid_y)', len (valid_y))
# дані тесту
test_x = залишився_x [int (len (залишився_x) * 0,5):]
test_y = залишився_y [int (len (залишився_y) * 0.5):]
print ('len (test_x)', len (test_x))
print ('len (test_y)', len (test_y))

train_data = TensorDataset (torch.tensor (np.asarray (train_x)), torch.tensor (np.asarray (train_y))))
valid_data = TensorDataset (torch.tensor (np.asarray (valid_x)), torch.tensor (np.asarray (valid_y)))
test_data = TensorDataset (torch.tensor (np.asarray (test_x)), torch.tensor (np.asarray (test_y))))

# завантажувачі даних
batch_size = 20 # кількість зразків, оброблених до оновлення моделі

train_loader = DataLoader (train_data, shuffle = True, batch_size = batch_size, drop_last = True)
valid_loader = DataLoader (valid_data, shuffle = True, batch_size = batch_size, drop_last = True)
test_loader = DataLoader (test_data, shuffle = True, batch_size = batch_size, drop_last = True)

dataiter = iter (train_loader) # доступ до вбудованих даних
sample_x, sample_y = dataiter.next ()
print ('Розмір вводу зразка:', sample_x.size ()) # batch_size, seq_length
print ('Зразок введення: \ n', sample_x)
print ()
print ('Зразок розміру етикетки:', sample_y.size ()) # batch_size
print ('Зразок етикетки: \ n', sample_y)
train_on_gpu = torch.device ("cpu") # Навчання на процесорі
клас SentimentLSTM (nn.Module):
" "
Модель RNN, яка буде використана для аналізу настроїв.
" "

def __init __ (self, vocab_size, output_size, embedding_dim, hidden_dim, n_layers, drop_prob = 0.5): # конструктор для визначення різних шарів, які ми маємо мати
" "
Ініціалізуйте модель, налаштувавши шари.
" "

super (SentimentLSTM, self) .__ init__ ()

self.vocab_size = vocab_size
self.output_size = розмір_виходу
self.n_layers = n_layers
self.hidden_dim = прихований_dim
# вбудовування та шари LSTM
self.embedding = nn.Embedding (vocab_size, embedding_dim)
self.lstm = nn.LSTM (вбудовування_dim, прихованих_dim, n_шарів,
dropout = drop_prob, batch_first = True)

# лінійний та сигмоподібний шари
self.fc = nn.Linear (hidden_dim, output_size)
self.sig = nn.Sigmoid ()

def forward (self, x, hidden): # перетворює дані, щоб отримати результат передбачення x = bach даних
" "
Виконайте прямий прохід нашої моделі на вхід і прихований стан.
" "
batch_size = x.size (0)
# вбудовування та lstm_out
embeds = self.embedding (x)
lstm_out, hidden = self.lstm (вбудовує, приховує)

#stack виводи lstm
lstm_out = lstm_out.contiguous (). view (-1, self.hidden_dim)

# залишеність і повністю зв’язаний шар
out = self.dropout (lstm_out)
out = self.fc (out)
# сигмоподібна функція
sig_out = self.sig (вихід)

# змінити форму, щоб спершу мати розмір партії
sig_out = sig_out.view (розмір_партії, -1)
sig_out = sig_out [:, -1] # отримати останню партію міток

# повертає останній сигмоподібний вивід і прихований стан
повернути sig_out, прихований

def init_hidden (self, batch_size):
вага = наступний (self.parameters ()). дані

якщо (train_on_gpu):
hidden = (weight.new (self.n_layers, batch_size, self.hidden_dim) .zero _ (). cpu (),
weight.new (self.n_layers, batch_size, self.hidden_dim) .zero _ (). cpu ())

# Примірник моделі
vocab_size = len (vocab_to_int) +1 # (+1 для заповнення 0) Розмір нашого словника або діапазон значень для нашого вводу
output_size = 1 # Розмір бажаного результату; кількість оцінок класів, які ми хочемо відобразити (пози/нега, конфлет/кастер).
embedding_dim = 40 # Кількість стовпців у таблиці пошуку інтеграції; розмір наших вкладень.
hidden_dim = 25 # Кількість одиниць у прихованих шарах наших клітин LSTM.

n_layers = 4 # Кількість рівнів LSTM у мережі

net = SentimentLSTM (vocab_size, output_size, embedding_dim, hidden_dim, n_layers)
друк (нетто)

# функція оптимізації та втрат
lr = 0,01 # Швидкість навчання
імпортувати torch.optim як оптиміст

критерій = nn.BCELoss () # обчислити помилки, щоб оптимізувати їх
optimizer = optim.Adam (net.parameters (), lr = lr) ## побудувати об'єкт оптимізатора

# параметри навчання
epochs = 6 # Кількість ітерацій через навчальний набір даних.
counter = 0 # лічильник
print_every = 10 # кількість
clip = 5 # відсікання градієнта (максимальне значення градієнта)
# перемістити модель на графічний процесор, якщо вона доступна
якщо (train_on_gpu):
net.cpu ()

# тренуватися протягом певної кількості епох
для e в діапазоні (епохи):
# ініціалізувати прихований стан
h = net.init_hidden (batch_size) # ініціалізувати приховані шари

# пакетний цикл
для входів, міток у train_loader:
лічильник + = 1
якщо (train_on_cpu):
inputs, labels = inputs.cpu (), labels.cpu ()
#print ("розмір партії:", batch_size)
# Створення нових змінних для прихованого стану, інакше
# ми б прокрутили всю історію тренувань
h = кортеж ([кожен.дані для кожного в h])

# нульовий накопичений градієнт
net.zero_grad ()

# отримати вихідні дані з моделі
inputs = inputs.type (torch.LongTensor)
вихід, h = чистий (входи, h)

# розрахувати збиток і виконати зворотний звіт
втрата = критерій (output.squeeze (), labels.float ())
loss.backward ()

# статистика втрат
якщо лічильник% print_every == 0:
# Отримайте втрату під час перевірки
val_h = net.init_hidden (розмір_партії)
val_losses = []
net.eval ()
для входів, мітки у valid_loader:

# Створення нових змінних для прихованого стану, інакше
# ми б прокрутили всю історію тренувань
val_h = кортеж ([кожен.дані для кожного в val_h])

якщо (train_on_cpu):
inputs, labels = inputs.cpu (), labels.cpu ()

inputs = inputs.type (torch.LongTensor)
вихід, val_h = нетто (входи, val_h)
val_loss = критерій (output.squeeze (), labels.float ())
val_losses.append (val_loss.item ())

print ("Епоха: <>/<>." .format (e + 1, епохи),
"Крок: <>.". Формат (лічильник),
"Втрата:.". Формат (loss.item ()),
"Втрата валу:" .format (np.mean (val_losses)))

# перевірити дані

test_losses = [] # втрата треку
правильна_число = 0
# init прихований стан
h = net.init_hidden (розмір_партії)
net.eval ()
# перебирати дані тесту
для входів, міток у test_loader:

# Створення нових змінних для прихованого стану, інакше
# ми б прокрутили всю історію тренувань
h = кортеж ([кожен.дані для кожного в h])
# print ("значення h: \ n", h)
якщо (train_on_gpu):
inputs, labels = inputs.cpu (), labels.cpu ()

# отримати прогнозовані результати
inputs = inputs.type (torch.LongTensor)
вихід, h = чистий (входи, h)

# обчислити збиток
test_loss = критерій (output.squeeze (), labels.float ())
test_losses.append (test_loss.item ())
#print (test_loss.item ())

# перетворення вихідних ймовірностей у передбачуваний клас (0 або 1)
pred = torch.round (output.squeeze ()) # округляється до найближчого цілого числа
#pred = pred.argmax (dim = 1, keepdim = True)
# порівняти передбачення із справжньою міткою
виправлений_тензор = pred.eq (labels.float (). view_as (pred))
правильний = np.squeeze (correct_tensor.cpu (). numpy ())
num_correct + = np.sum (правильно)
#print (num_correct)

# - Статистика! - ##
# середня втрата тесту
print ("Тестова втрата:" .format (np.mean (test_losses)))

# точність усіх даних тесту
test_acc = num_correct/len (test_loader.dataset)
print ("Тест точності:%". формат (test_acc * 100))

def tokenize_review (test_review):
test_review = test_review.lower () # нижній регістр
# позбутися пунктуації
test_text = '' .join ([c для c у test_review, якщо c не в розділових знаках])

# поділ на пробіли
test_words = test_text.split ()

# лексеми
test_ints = []
test_ints.append ([vocab_to_int [слово] для слова в test_words])

test_review_neg = 'Це найгірший ноутбук за всю історію.' # речення для тестування

передбачити def (net, test_review, length_length = 200):

net.eval ()
# tokenize огляд
test_ints = tokenize_review (test_review)

# pad токенізована послідовність
seq_length = довжина_послідовності
особливості = особливості_паду ​​(тестові_інці, довжина_дов)

# перетворити в тензор, щоб перейти у вашу модель
feature_tensor = torch.from_numpy (np.asarray (особливості))
batch_size = feature_tensor.size (0)

# ініціалізувати прихований стан
h = net.init_hidden (розмір_партії)

# отримати вихідні дані з моделі
feature_tensor = feature_tensor.type (torch.LongTensor)
вихід, h = net (функція_тензор, h)

# перетворення вихідних ймовірностей у передбачуваний клас (0 або 1)
pred = torch.round (output.squeeze ())
#printing вихідне значення, перед округленням
print ('Значення передбачення, попереднє округлення:' .format (output.item ()))

# друкувати власну відповідь
# друкувати власну відповідь
якщо (pred.item () == 1):
print ("Виявлено позитивний відгук!")
elif (pred.item () == 0):
print ("Виявлено негативний огляд.")
elif (pred.item () == 2):
print ("виявлено огляд конфлекту.")
ще:
print ("виявлено нейтральний огляд.")

seq_length = 200
передбачити (net, test_review_neg, seq_length)

Я новачок у обробці текстів за допомогою python (pytorch) і написав процес аналізу настроїв за допомогою повторюваних нейронних мереж (RNN), реалізованих за допомогою короткострокового довгострокового архітектурного терміну пам'яті (LSTM), але мій код не завжди повертає правильний результат і зміни точності при кожному запуску .

Запитання: Що можна зробити для підвищення точності? І отримати правильний результат ?