aitech-eks-pub/wyk/pytorch-regression/linear0.py

69 lines
2.0 KiB
Python
Executable File

#!/usr/bin/env python3
import sys
import torch
# Preprocessing i wektoryzację tekstów wydzialamy do osobnego modułu,
# z którego będzie korzystał zarówno kod do uczenia, jak i predykcji.
from analyzer import vectorizer, vector_length, process_line, vectorize_text
# Nasz model to zestaw wag w. Na koniec dojdziemy do modeli
# Transformer o wielu milionach wag; w pewnym sensie algorytm
# uczenia się nie zmieni.
# W naszym zadaniu lepiej zacząć od zerowych wag zamiast losowych.
# Znaczenie `requires_grad` zostanie omówione w kolejnym skrypcie.
w = torch.zeros(vector_length, dtype=torch.double, requires_grad=False)
# Hiperparametr uczenia
learning_rate = torch.tensor(.0032, dtype=torch.double)
def model(w, x):
# @ to iloczyn wektorów/macierzy w PyTorchu
return x @ w
# Funkcja kosztu.
def loss_fun(y_hat, y_exp):
return (y_hat - y_exp)**2
# Co ile kroków będziemy wypisywali informacje o średniej funkcji kosztu.
# To nie jest hiperparametr uczenia, nie ma to żadnego, ani pozytywnego, ani
# negatywnego wpływu na uczenie.
step = 5000
i = 1
closs = torch.tensor(0.0, dtype=torch.double, requires_grad=False)
for line in sys.stdin:
content, y_exp = process_line(line)
x = vectorize_text(content)
# wartość z predykcji
y_hat = model(w, x)
# wyliczamy funkcję kosztu
loss = loss_fun(y_hat, y_exp)
# Obliczamy gradient i aktualizujemy wagi.
# TU SIĘ ODBYWA UCZENIE!
grad = (y_hat - y_exp)
w = w - learning_rate * x * grad
# (Niedogodność tej wersji: jeśli zmienimy model lub funkcję kosztu,
# będziemy musieli zróżniczkować wszystko i ustalić formułę na grad.
# za jakiś czas pokazujemy uśrednioną funkcję kosztu
closs += loss
if i % step == 0:
print("Sample item: ", y_exp.item(), " => ", y_hat.item(),
" | Avg loss: ", (closs / step).item())
closs = torch.tensor(0.0, dtype=torch.double, requires_grad=False)
i += 1
# serializujemy nasz model
torch.save(w, "model.bin")