Zmienne niezależne i zależne

Ciekawe przykłady:

Independent and Dependent Variable Examples

  • In a study to determine whether how long a student sleeps affects test scores, the independent variable is the length of time spent sleeping while the dependent variable is the test score.
  • You want to compare brands of paper towels, to see which holds the most liquid. The independent variable in your experiment would be the brand of paper towel. The dependent variable would be the amount of liquid absorbed by a paper towel.
  • In an experiment to determine how far people can see into the infrared part of the spectrum, the wavelength of light is the independent variable and whether the light is observed (the response) is the dependent variable.
  • If you want to know whether caffeine affects your appetite, the presence/absence of the amount of caffeine would be the independent variable. How hungry you are would be the dependent variable.
  • You want to determine whether a chemical is essential for rat nutrition, so you design an experiment. The presence/absence of the chemical is the independent variable. The health of the rat (whether it lives and can reproduce) is the dependent variable. If you determine the substance is necessary for proper nutrition, a follow-up experiment would be to determine how much of the chemical is needed. Here, the amount of chemical would be the independent variable and the rat health would be the dependent variable

Cały artykuł: https://www.thoughtco.com/independent-and-dependent-variable-examples-606828

Dijkstra w Pythonie

graf = {}
graf[“start”] = {}
graf[“start”][“a”] = 7
graf[“start”][“b”] = 3

graf[“a”] = {}
graf[“a”][“meta”] = 2

graf[“b”] = {}
graf[“b”][“a”] = 4
graf[“b”][“meta”] = 6

graf[“meta”] = {}

nieskonczonosc = float(“inf”)
koszty = {}
koszty[“a”] = 7
koszty[“b”] = 3
koszty[“meta”] = nieskonczonosc

rodzice = {}
rodzice[“a”] = “start”
rodzice[“b”] = “start”
rodzice[“meta”] = None

przetworzone = []

def znajdz_najtanszy_wezel(koszty):
najnizszy_koszt = float(“inf”)
wezel_najnizszego_kosztu = None
for wezel in koszty:
koszt = koszty[wezel]
if koszt < najnizszy_koszt and wezel not in przetworzone:
najnizszy_koszt = koszt
wezel_najnizszego_kosztu = wezel
return wezel_najnizszego_kosztu

wezel = znajdz_najtanszy_wezel(koszty)

#W algorytmie Dijkstry pojawiają nam się
#wagi poszczególnych węzłów. Metoda ta
#szuka najtańszego węzła, który nie został
#jeszcze przetworzony.

while wezel is not None:

#Pętla pobiera kolejne wartości
#węzłów, aż wszystkie zostaną przetworzone.
#Gdy ich zabraknie pętla zakończy swoje
#działanie.

koszt = koszty[wezel]

#Koszt z analizowanego wezla
#dodawany jest do zmiennej “koszt”.

sasiedzi = graf[wezel]

#Do zmiennej “sasiedzi” dopisywana
#jest zawartość danej tablicy skrótów
#sąsiednich węzłów.

for n in sasiedzi.keys():

#Pętla dzięki metodzie keys() przegląda
#wszystkich sąsiadów danego węzła.

nowy_koszt = koszt + sasiedzi[n]

#”nowy_koszt” zawiera w sobie sumę
#kosztu dotarcia do danego węzła
#i odległości (koszt) między tym danym
#węzłem, a jego sąsiadem.

if koszty[n] > nowy_koszt:

#Tutaj porównujemy koszt dotarcia do
#węzła z nowym kosztem, który wynika
#z przejścia do tego samego celu (węzła)
#inną drogą.

koszty[n] = nowy_koszt

#Jeśli nowa droga okazała się mniej
#kosztowna, to dopisujemy ją do
#naszych kosztów.

rodzice[n] = wezel

#Pociąga to również za sobą to, że
#analizowany przez nas węzeł staje
#się naszym rodzicem.

przetworzone.append(wezel)

#Do przeznaczonej do tego tablicy dodajemy
#sprawdzony przez nas węzeł.

wezel = znajdz_najtanszy_wezel(koszty)

#Dalsze szukanie.

print(“Koszt od startu do a, od startu do b i od startu do mety, przedstawiaja sie nastepujaco:”)
print(koszty)

Grafy i wyszukiwanie wszerz, podstawy

Kodzik do użycia i przeanalizowania. Wcięcia do poprawienia (->Python).

from collections import deque

#Do utworzenia kolejki będziemy potrzebowali użyć
#metody deque(), stąd z modułu collections importujemy
#deque.

graf = {}

#Inicjalizujemy zmienną graf, posłuży nam jako zawartość
#naszych tablic skrótów.

graf[“Stach Malarz”] = [“Ryszard Hydraulik”,
“Paweł Motorniczy”,
“Czesław Śpiewak”]

#Każda z osób, w teorii grafów, tworzy
#osobny węzeł.”Stach Malarz” jest połączony z
#”Ryszard Hydraulik”, “Paweł Motorniczy”,
#”Czesław Śpiewak”. Moglibyśmy
#wyobrazić sobie, że Stach Malarz ma znajomych
#Ryszarda, Pawła i Czesława, na jednym z portali
#społecznościowych.

def sprawdz(nazwisko):

#Tworzymy metodę, która będzie nam sprawdzała czy
#aktualnie wybrana osoba jest tą, którą szukamy.

przeszukiwana_kolejka = deque()

#Dzięki metodzie “deque()” tworzymy nową kolejkę.

przeszukiwana_kolejka += graf[nazwisko]

#Do naszej kolejki dodajemy tablicę, jeśli będzie,
#to ‘graf[“Stach Malarz”]’, to do przeszukiwanej
#kolejki dopisze się “Ryszard Hydraulik”,
#”Paweł Motorniczy”, “Czesław Śpiewak”.

sprawdzeni = []

#tutaj deklarujemy sobie tablice, do której trafią
#ci których już sprawdziliśmy.

while przeszukiwana_kolejka:
osoba = przeszukiwana_kolejka.popleft()

#Bierzemy osobę z przodu kolejki i dopisujemy
#ją do zmiennej “osoba”.

if not osoba in sprawdzeni:

#Jest to warunek, który pozwala odfiltrować
#osoby, które już sprawdziliśmy.

if jesli_osoba_jest_motorniczym(osoba):
print(osoba + ” jest osobą, którą szukamy”)
return

#W naszej “zabawie” z kodem szukamy,
#osoby, która jest motorniczym.

else:
przeszukiwana_kolejka += graf[nazwisko]
sprawdzeni.append(osoba)

#Gdy nie znajdziemy szukanej osoby
#to do zmiennej “przeszukiwana_kolejka”
#dopisywana jest kolejna osoba.
#A sprawdzona osoba, która okazała się
#nie być motorniczym trafia do tablicy
#”sprawdzeni”

def jesli_osoba_jest_motorniczym(nazwisko):
return “Paweł Motorniczy” == nazwisko

#Deklarujemy metodą, która uruchomi się
#podczas gdy program będzie przechodził
#przez pętlę “if”. Metoda zwraca True,
#gdy natrafi w tablicy, na Pawła motorniczego.

sprawdz(“Stach Malarz”)

Wyszukiwanie Binarne

Kod w Pythonie. Polecam skopiować do IDE i tam przeanalizować.

from math import floor

#Importujemy metodę “floor()”, z modułu “math”. Metoda ta zaokrągla wartości. Jeśli ma do czynienia z liczbą dodatnią, to usuwa to co znajduje się po przecinku (np. floor(29.98), zwróci nam 29, dla floor(-29.98), będzie to -30).

def Wyszukiwanie_Binarne(Szereg, Wyszukiwany_Element):
n = len(Szereg)

#Do zmiennej “n”, dzięki metodzie len() zliczamy ilość elementów naszego szeregu.

L = 0

#Zmiennymi “L” i “R” dzielimy szereg, na “lewą” i “prawą” stronę.

R = n-1

#Od całej długości szeregu odejmujemy: -1, ponieważ zaczynamy liczyć od 0, element o indeksie “0” jest naszym pierwszym elementem, „n-1” będzie ostatnim.

while L <= R:

#Mamy warunek sprawdzający czy element po lewej stronie jest elementem wcześniejszym niż ten po prawej stronie. Inaczej nie ma sensu uruchamiać pętli.

mid = floor((L+R)/2)

#Wszukujemy element o środkowym indeksie, licząc średnią arytmetyczną granicznych elementów, dopisując wynik do zmiennej „mid”.

if Szereg[mid] < Wyszukiwany_Element:

#Tutaj sprawdzamy czy wartość elementu kryjąca się pod danym indeksem jest mniejsza niż wartość szukanego elementu

L = mid + 1
elif Szereg[mid] > Wyszukiwany_Element:
R = mid – 1
else:
return mid
return -1

#Algorytm jest mało skomplikowany. Przemierzamy nasz szereg w lewo i w prawo przyrównując napotkane wartości z wartością, którą chcemy znaleźć.

#Kwintesencją algorytmu jest zawężanie obszarów poszukiwania porównując wartości porównywane z szukaną. Wyszukiwanie binarne ma sens jeśli przeszukujemy posortowany ciąg.

A = [2,4,5,8,11,13,15,18,25]

#Jest to przykładowa lista wartości. W tym przykładzie nie pobieramy danych od użytkownika. Chodzi o zaprezentowanie algorytmu.

term = 18

#Szukana przez nas wartość.

index = Wyszukiwanie_Binarne(A, term)

#Deklarujemy zmienną “index”, która zawrze w sobie wynik metody “binary_search().”

if index >= 0:
print(“{} jest w index {}”.format(A[index], index))
else:
print(“Nie odnaleziono.”)

#Sprawdzamy czy szukana przez nas liczba istnieje. Jeśli tak, to program formatuje wartości i wyświetli ją na ekranie, podając jej wartość oraz miejsce na liście (numer indeksu elementu).

Wstęp do uczenia maszynowego (3)

Był przykład, na uczenie nadzorowane, to teraz napiszmy coś o uczeniu nienadzorowanym.

Uczenie nienadzorowane z kolei moglibyśmy określić takim “wzorem”:
Dane + Algorytm = X (“X” to nasza niewiadoma)

Dane – do modelu wprowadzamy nieoznakowane dane. Przypomnijmy sobie przykład z klasyfikowaniem e-maili jako spam lub nie-spam. Okej, już to mamy za sobą. Mamy już odcedzony spam od nie spamu. Co dalej możemy zrobić z naszą pocztą. Możemy użyć kolejnego algorytmu, tym razem tego z pod znaku uczenia nienadzorowanego.

Co taki algorytm może dla nas zrobić? Może na podstawie treści (poszczególnych słów użytych w treści wiadomości jak i sposobie ich ułożenia) pogrupować odpowiednio e-maile, które zakwalifikowaliśmy już wcześniej jako e-maile normalne.

Może okazać się algorytm zauważył, że większość e-maili można podzielić, powiedzmy, na kilka grup: e-maile służbowe, e-maile z rodziną, pozostałe. Takie 3 grupy jesteśmy w stanie sobie wyobrazić i zinterpretować dość łatwo. Dla maszyny będą to różne klasy, maszyna nie będzie widziała tego, co my widzimy, tzn. że to są maile służbowe, a to rodzinne, ona będzie “zdawać sobie sprawę”, z różnic jakie występują miedzy klasami i z podobieństw w tych samych klasach.

Wstęp do uczenia maszynowego (2)

Machine Learning. Kiedy ma sens?

Tak jak z większością rzeczy, tak samo i z uczeniem maszynowym są sytuacje, gdy coś ma sens, a w innych warunkach, staje się nieprzydatne.

ML na pewno spisze się, w sytuacji, gdy program wymaga kodu złożonego na przykład z wielu warunków. Załóżmy mielibyśmy do napisania kod składający się m.in. z  1000, a może i więcej, może 10000 tys. instrukcji “IF”, a może i jeszcze więcej linii kodu, a to zaledwie i tak stanowiłoby jedynie jakąś mniejszą część programu.

Kod nie musiałby, nawet jakoś szczególnie być skomplikowany pod względem logicznym, natomiast byłoby go dużo i niemalże za każdym razem musielibyśmy zmienić go odrobinę, ale maszyna nie byłaby w stanie “odgadnąć”, co ma zmienić, mimo że zmiany mogłyby wydawać się nam niewielkie i proste.

I w tej chwili przychodzi nam na pomoc uczenie maszynowe, ponieważ może się okazać, że jeden algorytm uczenia maszynowego jest w stanie zrobić za nas kupę roboty, wykonując pożądane przez nas operacje.

Kiedy jeszcze jest sens użyć Machine Learning? Wtedy gdy zwyczajnie tradycyjne sposoby nie dały pozytywnego skutku. Eksperymentując, może okazać się, że użycie ML, dało nam gotowy wynik, albo naprowadziło nas na właściwe tory, co wynikło na przykład z tego, że algorytm wykrył pewne korelacje, których nasze oko i umysł (czy też inne narzędzia) nie wychwyciły dając nam kolejne informację, na temat naszego przedmiotu badań.

Kiedy jeszcze ML ma sens? Na pewno, sami to zobaczymy.

Wstęp do Uczenia Maszynowego (1)

Dobry będzie przykład z oznaczeniem e-maili jako spam.

Dlaczego? Powiedziałbym, z dużą ufnością, że posiadasz jakąś skrzynkę pocztową wyposażoną, w jakiś anty-spamowy system.

Czy zastanawiało Cię jak ten system działa?

Okej więc tak: Mamy wiadomości e-mail. Weźmy sobie, powiedzmy, zbiór 1000 e-maili. Te 1000 e-maili niech będzie naszym zbiorem treningowym. Każdy z tych e-maili oznaczamy sobie jako “spam” albo “normalny”. Oznaczamy te e-maile z góry. To my wiemy, który e-mail jest spamem, a który nie.

Kolejnym zbiorem będzie zbiór testowy. Tworząc model (czyli tą naszą czarną skrzyneczkę) chcemy uzyskać jego największą wydajność, ale jak zweryfikować to czy taki model jest w naszym mniemaniu wydajny?

Do tego użyjemy zbioru testowego. Zbiór testowy będzie zawierał gotowe odpowiedzi. Będzie zawierał dane określające “status” każdego z e-mailów: “Ten e-mail to spam. Ten e-mail jest OK. A ten e-mail jest spamem”. Tak będzie oznaczona każda wiadomość.

Innymi słowy, będzie to zbiór, który będzie zawierał poprawne (i oczekiwane jako wynik pracy modelu) odpowiedzi. Pod tym względem będziemy sprawdzać nasz model wywiązuje się ze swojej roli.

No to jedziemy. Wrzucamy dane treningowe. Mamy tam powiedzmy 400 e-maili oznaczonych jako spam i 600 e-maili oznaczonych jako normalna poczta.

Przepuszczamy, to przez algorytm/y uczenia maszynowego. Nie będę się zagłębiał w to jak te algorytmy działają (to nie jest materiał na ten wpis).

Istotniejszy jest bardziej ogólny sens: algorytm uczenia maszynowego w tym momencie zaczyna doszukiwać się różnych powiązań między e-mailami tego samego rodzaju np. (e-mail) spam i (e-mail) spam i różnić między e-mailami np. (e-mail) spam i (e-mail) normalny.

Dobra, zakładamy, że z lepszym lub gorszym wynikiem wytrenowaliśmy model. Wytrenowany model “nauczył się”, że tytuł i tekst przykładowego spamu charakteryzuje się tym, tym i tym, a z kolei tytuł i treść normalnego e-maila charakteryzuje się tym, tym i tym.

No dobra, ale algorytm sobie tam podziałał, ale skąd wiemy, ze komputer zrobił dobrze swoją robotę i ten model faktycznie będzie potrafił prawidłowo zakwalifikować nowe e-maile, jako spam, albo normalny.

No dobra, to bierzemy załóżmy 50 e-maili i wrzucamy do modelu. Oczywiście my wiemy, który e-mail to spam, który to e-mail normalny. To jest nasz zbiór testowy. Testujemy nasz model.

Przepuszczamy te e-maile przez model i mamy wynik. Model wskazał nam, że 20 e-maili jest normalnych, a 30 to spam. Ale co to? W zbiorze testowym mieliśmy 25 normalnych e-maili i 25 spamów. No nie jest dobrze. Model nie wykazał się w pełni.

Jak się domyślamy idealna sytuacja to taka kiedy model właściwie oznacza przychodzące e-maile i te właściwe przenosi do podfolderu “spam”.

Natomiast wymaga, to odpowiednio dużej ilości danych, w tym przypadku musimy do modelu dostarczyć odpowiednio dużo przykładowych e-maili, już z góry, właściwie oznaczonych przez nas jako “spam”, albo “e-mail normalny” (żeby model miał więcej materiału na podstawie, którego będzie mógł lepiej wnioskować) albo wykorzystać bardziej wyrafinowane sposoby trenowania modelu (o tym będę jeszcze pisał).

Trzeba to sobie przekalkulować. W naszym przypadku dostarczenie większej ilość oznaczonych e-maili, na pewno zrobiłoby robotę.

W skrócie, na koniec. Mamy taką sytuację (oczywiście nie chodzi tu o sens matematyczny, ale bardziej intuicyjny):

DANE + X = WYNIK

DANE – to oznaczone e-maile jako spam lub nie spam
X – to nasz “filtr”/model, który w naszym wzorze jest niewiadomą, my go musimy odkryć, wytrenować
WYNIK – to nasz rezultat, my znamy wynik, nie jest naszą niewiadomą, pozwala nam “wyliczyć” X

Co warto zapamiętać, jest to przykład uczenia nadzorowanego. Ten “nadzór” stanowimy My, dostarczając dane testowe i sprawdzając czy model właściwie je rozpoznaje.