Kluczowym wydaje się posiadanie gotowego zbioru danych, jeśli chcemy tworzyć modele. Jest to prawdą. Zadajmy sobie jednak pytanie. Czy możemy stworzyć model bez danych?

Możemy. Musimy zostać Doktorem Frankensteinem.

Wyobraźmy sobie dane jako żywy organizm. Co robimy, jeśli nie mamy żywego organizmu? Bierzemy martwą materię (czyt. zwłoki) i ją ożywiamy.

Zanim zaczniemy eksperymenty, krótko o sygnale i szumie.

Sygnał i Szum

Historia o pewnym prozaicznym spotkaniu.

Kończysz właśnie zajęcia w szkole muzycznej, sekcja skrzypiec. Wychodząc, zauważasz po drugiej stronie ulicy swojego przyjaciela.

Odkładasz futerał ze skrzypcami na ziemię, składasz dłonie w tubę i krzyczysz. Zdaje się, że Cię zauważył. Tak. Macha do Ciebie. O, sam zaczyna coś krzyczeć. Jest jednak spory hałas. Pędzące samochody widocznie mają zielone światło a ograniczenie do 50 km/h jest stanowczo łamane. Słyszysz coś jednak:

Trzy Pizze

Cieszysz się, bo w sumie jesteś głodny i zjadłbyś coś chętnie. A skoro i spotkałeś przyjaciela to tym lepiej, będziesz jadł w towarzystwie. Kolega jednak krzyczy dalej:

Trzy Piece

To już raczej nie ma sensu. Jest hałas i może mu chodziło, że Upiecze. To by było nawet lepsze. Zaprasza Cię do siebie. Upiecze sam i zjecie u niego. To nawet lepiej, bo masz chwilę czasu. Jednak to nie wszystko, bo słyszysz, jak dalej krzyczy. Samochody się zatrzymały. Widocznie jest już czerwone. Wtedy słyszysz wyraźnie:

SKRZYPCE!!!

Kierujesz wzrok na swoje skrzypce i faktycznie coś z nimi nie tak. Mianowicie nie ma ich. Odwracasz się i widzisz, jak Twoje skrzypce zmieniły właściciela, który dosyć sprawnie się oddala.

Sygnałem w całej tej sytuacji był krótki komunikat od przyjaciela: SKRZYPCE!!!

Z powodu jadących samochodów (hałasu, jaki wywoływały), odległości dzielącej cię od przyjaciela (fala dźwiękowa słabła), tego, że byłeś głodny, co zaburzyło twoją percepcję (odbiornik rozstrojony), komunikat przez długi czas był znacząco zniekształcony.

Wszystkie czynniki, które sprawiły, że sygnał był niezrozumiały, zawierają się w pojęciu szumu.

Formalnie mamy więc:

  • Sygnał: prawdziwy komunikat, prawdziwy związek, prawdziwa zależność,
  • Szum: wszystko to, co nie jest sygnałem, jest losowe, niedające się ująć w struktury.

Przykłady sygnału i szumu w zbiorach danych:

  • Rynek nieruchomości:
    • Sygnał – duże mieszkanie duża cena,
    • Szum – duże mieszkanie niska cena.
  • Rynek pracy:
    • Sygnał – źle opłacani pracownicy odchodzą,
    • Szum – źle opłacani pracownicy zostają.
  • Sztuczna inteligencja:
    • Sygnał – automatyczny samochód reaguje na światło czerwone
    • Szum – automatyczny samochód reaguje na błysk wywołany wschodem słońca.

Dlaczego podział na szum i sygnał jest taki istotny? Zasadniczo całe uczenie maszynowe polega na wygenerowaniu modelu, który dobrze wyłapuje sygnał, a ignoruje szum.

Laboratorium

Jako naukowcy potrzebujemy odpowiedniego środowiska do naszych eksperymentów.

Za laboratorium posłuży nam Jupyter Notebook, o którym pisałem tutaj. Potrzebujemy też specjalnej aparatury, czyli 6 Niezbędnych Narzędzi:

  • Python – język programowania, w którym wszystko stworzymy,
  • NumPy – dostarczy nam poszczególnych danych,
  • Pandas – połączy dane w jedną całość,
  • Matplotlib i Seaborn – pokaże jak wyglądają nasze zwłoki,
  • Scikit Learn – dostarczy prosty model regresji liniowej.

Wszystkie powyższe narzędzia wykorzystamy do przeprowadzania symulacji.

Potęga Symulacji

Symulacja spełnia dwie ważne role w pracy z danymi:

  • może służyć do rozwiązywać złożonych problemów,
  • pozwala prezentować kluczowe koncepcje.

Z symulacją możemy z góry określić prawdziwy stan świata i przetestować różne modele, aby sprawdzić, jak dobrze sobie radzą.

Połączmy więc wszystko w jedną całość i tchnijmy trochę życia w tym smutnym jak … (wstaw co chcesz) poście.

Tworzymy Sygnał i Szum

Zacznijmy od sygnału i szumu. Mamy prawdziwy związek między danymi, czyli Sygnał. Na przykładzie rynku nieruchomości: cena mieszkania rośnie, gdy powierzchnia mieszkania rośnie. Dla uproszczenia jest to stała, liniowa zależność, którą można opisać wzorem funkcji znanym jako:

y = x

Wiemy, że świat nie jest idealny i pojawia się szum. Szum, który jest losowy. Funkcja powinna wyglądać więc tak:

y = x + szum

Zobaczmy, jak wygląda nasz sygnał zmieniony przez szum. Prawda, że dane wyglądają jak żywe?

# import odpowiednich bibliotek
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline
import seaborn as sns
sns.set_style('darkgrid')

# początkowe ustawienia seed(321) aby odtworzyć losowość, figsize aby zwiekszyć rozmiar wykresu
np.random.seed(321)
fig = plt.figure(figsize=(16,8))

# tworzenie sygnału
x = np.linspace(0,10,100)
y = x

# tworzenie szumu o rozkładzie normalnym
szum = np.random.normal(0,1.5,100)

# sygnał zmieniony przez szum - pojedyńcze fioletowe punkty
plt.scatter(x, (x +szum),color='purple')
wykres sygnału i szumu
Nasze Obserwacje Jak Żywe.

Wiemy, jaki jest prawdziwy związek między naszymi danymi. Sami przecież go stworzyliśmy. Dodajmy go na wykresie w postaci zielonej linii i wygenerujmy wykres na nowo.

fig = plt.figure(figsize=(16,8))

# wykres sygnału - zielona linia prosta
plt.plot(x,y,color='green',ls='-',lw=10,alpha=0.5)
# sygnał zmieniony przez szum na fioletowo
plt.scatter(x, (x +szum),color='purple')
sygnał i szum
Żywe Dane: Sygnał (zielona linia) i Sygnał z Szumem (fioletowe punkty)

Model Oparty Średnią

Spróbujmy zrobić pierwszy, najprostszy model. Model oparty na średniej z y(ceny mieszkań) i zobaczmy, jak pasuje do naszych obserwacji.

# sygnał zmieniony przez szum na fioletowo
fig = plt.figure(figsize=(16,8))
plt.scatter(x, (x +szum),color='purple')
# model oparty o średnią z y
plt.plot(x,[np.mean(y)]*len(y),color='yellow',marker='*', markersize=8)
model średniej
Model oparty o średnią z cen mieszkań (y)

Mamy pierwszy model oparty o średnią z y (cen mieszkań). Jest tu jednak pewien problem. Okazuje się, że cena jest taka sama cały czas. Model, który w ogóle nie uwzględnia zmiennych. Nie jest istotny nawet metraż mieszkania. Model raczej słabo spisujący się w realnych warunkach.

Model Regresji Liniowej

Skorzystajmy więc z biblioteki Scikit Learn i modelu regresji liniowej. Zgrabne i obszerne wyjaśnienie czym jest regresja liniowa można znaleźć tutaj:

# import biblioteki z modelem regresji liniowej
from sklearn.linear_model import LinearRegression
# tworzymy instancję modelu regresji liniowej
lm = LinearRegression()
# tworzymy obiekt DataFrame z naszych danych
df = pd.DataFrame({'x':x,'y':y})

# rozdzielamy dane na atrybuty i zmienna celu
atrybuty = df.drop('y',axis=1)
zmienna_celu = df.y

# trenujemy model
lm.fit(atrybuty, zmienna_celu)

# tworzymy wykres sygnału, naszych obserwacji (sygnał + szum), i nasz model
fig = plt.figure(figsize=(16,8))
# sygnał na zielono
plt.plot(x,y,color="green",linewidth=10)
# sygnał + szum na fioletowo
plt.scatter(x, (x +szum),color='purple')
# model na żółto
plt.plot(atrybuty,lm.predict(atrybuty),color='yellow',marker='*', markersize=8)
fig.savefig('model.png')
model regresji liniowej
Idealnie dopasowany model

Wnioski

Sukces, nasz model (żółta linia) pokrywa się niemal idealnie z sygnałem (zielona linia). Dzięki zastosowaniu regresji liniowej odkryliśmy prawdziwy związek w naszych danych ten, który sami zaprojektowaliśmy.

Oczywiście nie jest to do końca ścisłe i brakuje tutaj istotnego elementu, a mianowicie podziału na zbiór danych treningowych i zbiór danych testowych. Wytrenowaliśmy model za pomocą danych treningowych i prognozę zrobiliśmy na bazie tych samych danych. Powinniśmy wygenerować nowy losowy zbiór danych i jego użyć do predykcji. Warto też sprawdzić jakość naszego modelu korzystając z mierników ilościowych. O tym w innym poście.

Zrobiliśmy jednak coś z niczego. Nie mając nic, wygenerowaliśmy sobie dane, zrobiliśmy pierwszy model regresji liniowej, dopasowaliśmy do naszych danych i zobaczyliśmy je na wykresie. Możemy krzyknąć z umiarkowanie szaloną radością.

Podsumowanie

W tym poście zostałeś wtajemniczony w tajną sztukę powoływania danych do życia i:

  • wiesz, czym jest sygnał i szum oraz poznałeś kilka przykładów z życia wziętych,
  • rozumiesz dlaczego sygnał i szum jest istotny,
  • umiesz wygenerować sobie testowy zbiór danych, zarówno sygnał, jak i szum dzięki NumPy,
  • wiesz jak to połączyć w jeden obiekt DataFrame,
  • potrafisz pokazać to na wykresie z użyciem Matplotlib,
  • umiesz już stworzyć prosty model oparty o średnią ze zmiennej celu,
  • potrafisz wreszcie stworzyć model regresji liniowej.

I dobrze wiesz, że to dopiero początek, bo skoro masz już zdolność powoływania do życia, możesz sprawdzić inne funkcje z innym szumem i innymi modelami. Wykreuj swoją rzeczywistość i baw się w jej prognozowanie.

Dziękuję, że dotrwałeś do końca mimo mrocznej aury wiszącej nad tym artykułem.