5.8 KiB
5.8 KiB
Wczytanie zbioru danych do postaci DataFrame
from datasets import load_dataset
import pandas as pd
import torch
from torch.nn.utils.rnn import pad_sequence
hf_dataset = load_dataset("mteb/tweet_sentiment_extraction")
df = pd.DataFrame(hf_dataset["train"])
test_df = pd.DataFrame(hf_dataset["test"])
c:\Users\ryssta\AppData\Local\anaconda3\envs\python39\lib\site-packages\tqdm\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html from .autonotebook import tqdm as notebook_tqdm
Przykładowa modyfikacja tekstu (analogiczne operacje należy wykonać dla podzbioru test)
df = pd.DataFrame(hf_dataset["train"])
print(df["text"].head(3))
df["text"] = df["text"].apply(lambda text_row: text_row.upper())
print(df["text"].head(3))
0 I`d have responded, if I were going 1 Sooo SAD I will miss you here in San Diego!!! 2 my boss is bullying me... Name: text, dtype: object 0 I`D HAVE RESPONDED, IF I WERE GOING 1 SOOO SAD I WILL MISS YOU HERE IN SAN DIEGO!!! 2 MY BOSS IS BULLYING ME... Name: text, dtype: object
Dodanie warstwy embedding z tokenem pad (czyli "zapychaczem" służącym do wypełniania macierzy)
padding_idx = 9
embedding = torch.nn.Embedding(10, 5, padding_idx=padding_idx)
pad_embedding = embedding(torch.LongTensor([9]))
print(pad_embedding)
tensor([[0., 0., 0., 0., 0.]], grad_fn=<EmbeddingBackward0>)
Padowanie sekwencji przy pomocy funkcji
input_token_ids = [[4,7,2], [7,3,2,7,5,3,2], [1,7,4,2,5]]
max_length = max(len(seq) for seq in input_token_ids)
padded_input = pad_sequence([torch.tensor(seq) for seq in input_token_ids], batch_first=True, padding_value=padding_idx)
lengths = [len(seq) for seq in input_token_ids]
print(padded_input)
print("Długości inputów")
print(lengths)
tensor([[4, 7, 2, 9, 9, 9, 9], [7, 3, 2, 7, 5, 3, 2], [1, 7, 4, 2, 5, 9, 9]]) Długości inputów [3, 7, 5]
Przepuszczanie embeddingów przez warstwę LSTM (przy pomocy funkcji padujących)
lstm_layer = torch.nn.LSTM(5, 5, 30, batch_first=True, bidirectional=True)
embedded_inputs = embedding(padded_input)
x = torch.nn.utils.rnn.pack_padded_sequence(embedded_inputs, lengths, batch_first=True, enforce_sorted=False)
output, (hidden, cell) = lstm_layer(x)
output, _ = torch.nn.utils.rnn.pad_packed_sequence(output, batch_first=True)
Zmienna hidden zawiera wszystkie ukryte stany na przestrzeni wszystkich warstw, natomiast zmienna output zawiera jedynie stany w ostatniej warstwie
Wartościami, które należy wykorzystać do klasyfikacji to (jedna z dwóch opcji):
- konkatenacja ostatniego i przedostatniego elementu ze zmiennej hidden (sieć jest dwukierunkowa, więc chcemy się dostać do stanów z ostatniej warstwy jednego oraz drugiego kierunku)
- pierwszy element dla każdego przykładu ze zmiennej out (tam jest automatycznie skonkatenowany output dla obu kierunków, dlatego mamy na końcu rozmiar 10)
print(hidden.shape)
print(output.shape)
torch.Size([60, 3, 5]) torch.Size([3, 7, 10])
torch.Size([6, 3, 5]) torch.Size([3, 7, 10])