Predstavitev
Včasih se zamenjuje z linearne regresije novinci – zaradi delitve termina regresija - logistična regresija se daleč razlikuje od linearne regresije. Medtem ko linearna regresija napoveduje vrednosti kot so 2, 2.45, 6.77 oz zvezne vrednosti, zaradi česar je regresija algoritem, logistična regresija napove vrednosti, kot so 0 ali 1, 1 ali 2 ali 3, ki so diskretne vrednosti, zaradi česar je Razvrstitev algoritem. Ja, imenuje se regresija vendar je a Razvrstitev algoritem. Več o tem čez trenutek.
Če torej vaš problem podatkovne znanosti vključuje zvezne vrednosti, lahko uporabite a regresija algoritem (linearna regresija je eden izmed njih). V nasprotnem primeru, če vključuje razvrščanje vnosov, diskretnih vrednosti ali razredov, lahko uporabite Razvrstitev algoritem (logistična regresija je eden izmed njih).
V tem priročniku bomo izvajali logistično regresijo v Pythonu s knjižnico Scikit-Learn. Pojasnili bomo tudi, zakaj slov “regresija” je prisoten v imenu in kako deluje logistična regresija.
Da bi to naredili, bomo najprej naložili podatke, ki bodo klasificirani, vizualizirani in predhodno obdelani. Nato bomo zgradili logistični regresijski model, ki bo razumel te podatke. Ta model bo nato ovrednoten in uporabljen za napovedovanje vrednosti na podlagi novih vnosov.
Motivacija
Podjetje, v katerem delate, je sklenilo partnerstvo s turško kmetijsko kmetijo. To partnerstvo vključuje prodajo bučnih semen. Bučna semena so zelo pomembna za prehrano ljudi. Vsebujejo dober delež ogljikovih hidratov, maščob, beljakovin, kalcija, kalija, fosforja, magnezija, železa in cinka.
V ekipi za podatkovno znanost je vaša naloga ugotoviti razliko med vrstami bučnih semen samo z uporabo podatkov – oz. razvrščanje podatke glede na vrsto semena.
Turška kmetija dela z dvema vrstama bučnih semen, ena se imenuje Çerçevelik in drugo Ürgüp Sivrisi.
Za razvrščanje bučnih semen je vaša ekipa sledila dokumentu iz leta 2021 »Uporaba metod strojnega učenja pri klasifikaciji bučnih semen (Cucurbita pepo L.). Genetski viri in razvoj pridelka iz Koklua, Sarigila in Ozbeka – v tem dokumentu je metodologija za fotografiranje in ekstrahiranje meritev semen iz slik.
Po zaključku postopka, opisanega v članku, so bile pridobljene naslednje meritve:
- Območje – število slikovnih pik znotraj meja bučnega semena
- Obseg – obseg bučnega semena v pikslih
- Dolžina glavne osi – tudi obseg v pikslih bučnega semena
- Dolžina manjše osi – majhna osna razdalja bučnega semena
- Ekscentričnost – ekscentričnost bučnega semena
- Konveksno območje – število slikovnih pik najmanjše konveksne lupine na območju, ki ga tvori bučno seme
- Obseg – razmerje med površino bučnega semena in slikovnimi pikami omejevalnega polja
- Ekvivalenten premer – kvadratni koren pomnožitve ploščine bučnega semena s štiri deljeno s pi
- Kompaktnost – delež ploščine bučnega semena glede na ploščino kroga z enakim obsegom
- Očistost – konveksno in konveksno stanje bučnih semen
- Zaokroženost – ovalnost bučnih semen brez upoštevanja popačenosti robov
- Razmerje – razmerje stranic bučnih semen
To so meritve, s katerimi morate delati. Poleg meritev je tu še Class oznaka za dve vrsti bučnih semen.
Za začetek razvrščanja semen uvozimo podatke in si jih začnimo ogledovati.
Razumevanje nabora podatkov
Opomba: Nabor podatkov o bučah lahko prenesete tukaj.
Po prenosu nabora podatkov ga lahko naložimo v strukturo podatkovnega okvira z uporabo pandas
knjižnica. Ker gre za datoteko excel, bomo uporabili read_excel()
metoda:
import pandas as pd
fpath = 'dataset/pumpkin_seeds_dataset.xlsx'
df = pd.read_excel(fpath)
Ko so podatki naloženi, lahko na hitro pokukamo v prvih 5 vrstic z uporabo head()
metoda:
df.head()
Rezultat tega je:
Area Perimeter Major_Axis_Length Minor_Axis_Length Convex_Area Equiv_Diameter Eccentricity Solidity Extent Roundness Aspect_Ration Compactness Class
0 56276 888.242 326.1485 220.2388 56831 267.6805 0.7376 0.9902 0.7453 0.8963 1.4809 0.8207 Çerçevelik
1 76631 1068.146 417.1932 234.2289 77280 312.3614 0.8275 0.9916 0.7151 0.8440 1.7811 0.7487 Çerçevelik
2 71623 1082.987 435.8328 211.0457 72663 301.9822 0.8749 0.9857 0.7400 0.7674 2.0651 0.6929 Çerçevelik
3 66458 992.051 381.5638 222.5322 67118 290.8899 0.8123 0.9902 0.7396 0.8486 1.7146 0.7624 Çerçevelik
4 66107 998.146 383.8883 220.4545 67117 290.1207 0.8187 0.9850 0.6752 0.8338 1.7413 0.7557 Çerçevelik
Tukaj imamo vse meritve v ustreznih stolpcih, naših lastnosti, in tudi Class stolpec, naš ciljna, ki je zadnji v podatkovnem okviru. Z uporabo lahko vidimo, koliko meritev imamo shape
atribut:
df.shape
Izhod je:
(2500, 13)
Rezultat oblike nam pove, da je v naboru podatkov 2500 vnosov (ali vrstic) in 13 stolpcev. Ker vemo, da obstaja en ciljni stolpec – to pomeni, da imamo 12 stolpcev funkcij.
Zdaj lahko raziščemo ciljno spremenljivko, bučno seme Class
. Ker bomo to spremenljivko predvideli, je zanimivo videti, koliko vzorcev vsakega bučnega semena imamo. Običajno je manjša kot razlika med številom primerkov v naših razredih, bolj uravnotežen je naš vzorec in boljše so naše napovedi.
Ta pregled lahko opravite tako, da vsak vzorec semena preštejete z value_counts()
metoda:
df['Class'].value_counts()
Zgornja koda prikazuje:
Çerçevelik 1300
Ürgüp Sivrisi 1200
Name: Class, dtype: int64
Vidimo lahko, da obstaja 1300 vzorcev Çerçevelik semena in 1200 vzorcev Ürgüp Sivrisi seme. Upoštevajte, da je razlika med njima 100 vzorcev, kar je zelo majhna razlika, kar je za nas dobro in kaže, da ni potrebe po uravnavanju števila vzorcev.
Oglejmo si tudi opisno statistiko naših funkcij z describe()
kako dobro so podatki porazdeljeni. Dobljeno tabelo bomo tudi prenesli z T
za lažjo primerjavo statistik:
df.describe().T
Končna tabela je:
count mean std min 25% 50% 75% max
Area 2500.0 80658.220800 13664.510228 47939.0000 70765.000000 79076.00000 89757.500000 136574.0000
Perimeter 2500.0 1130.279015 109.256418 868.4850 1048.829750 1123.67200 1203.340500 1559.4500
Major_Axis_Length 2500.0 456.601840 56.235704 320.8446 414.957850 449.49660 492.737650 661.9113
Minor_Axis_Length 2500.0 225.794921 23.297245 152.1718 211.245925 224.70310 240.672875 305.8180
Convex_Area 2500.0 81508.084400 13764.092788 48366.0000 71512.000000 79872.00000 90797.750000 138384.0000
Equiv_Diameter 2500.0 319.334230 26.891920 247.0584 300.167975 317.30535 338.057375 417.0029
Eccentricity 2500.0 0.860879 0.045167 0.4921 0.831700 0.86370 0.897025 0.9481
Solidity 2500.0 0.989492 0.003494 0.9186 0.988300 0.99030 0.991500 0.9944
Extent 2500.0 0.693205 0.060914 0.4680 0.658900 0.71305 0.740225 0.8296
Roundness 2500.0 0.791533 0.055924 0.5546 0.751900 0.79775 0.834325 0.9396
Aspect_Ration 2500.0 2.041702 0.315997 1.1487 1.801050 1.98420 2.262075 3.1444
Compactness 2500.0 0.704121 0.053067 0.5608 0.663475 0.70770 0.743500 0.9049
Z ogledom tabele, ko primerjamo v pomeni in standardni odklon (std
) stolpcev je razvidno, da ima večina funkcij povprečje, ki je daleč od standardnega odklona. To pomeni, da vrednosti podatkov niso skoncentrirane okoli srednje vrednosti, temveč bolj razpršene okoli nje – z drugimi besedami, imajo visoka variabilnost.
Tudi ob pogledu na minimalna (min
) in največja (max
) stolpce, nekatere funkcije, kot npr Area
in Convex_Area
, imajo velike razlike med najnižjo in najvišjo vrednostjo. To pomeni, da imajo tisti stolpci zelo majhne podatke in tudi zelo velike vrednosti podatkov oz večja amplituda med vrednostmi podatkov.
Z visoko variabilnostjo, visoko amplitudo in funkcijami z različnimi merskimi enotami bi večini naših podatkov koristilo, če bi imeli enako lestvico za vse značilnosti ali pomanjšana. Skaliranje podatkov osredotoči podatke okoli povprečja in zmanjša njihovo varianco.
Ta scenarij verjetno tudi nakazuje, da v podatkih obstajajo odstopanja in ekstremne vrednosti. Zato je najbolje imeti nekaj izstopno zdravljenje poleg skaliranja podatkov.
Obstaja nekaj algoritmov strojnega učenja, na primer drevesni algoritmi, kot je npr Naključna klasifikacija gozdov, na katere ne vplivajo velika varianca podatkov, odstopanja in ekstremne vrednosti. Logistična regresija je drugačen, temelji na funkciji, ki kategorizira naše vrednosti, na parametre te funkcije pa lahko vplivajo vrednosti, ki so izven splošnega trenda podatkov in imajo visoko varianco.
Čez nekaj časa bomo izvedeli več o logistični regresiji, ko jo bomo začeli izvajati. Za zdaj lahko nadaljujemo z raziskovanjem naših podatkov.
Opomba: V računalništvu obstaja priljubljen pregovor: “Smeti noter, smeti ven” (GIGO), ki je zelo primeren za strojno učenje. To pomeni, da ko imamo nepotrebne podatke – meritve, ki ne opisujejo pojavov samih, podatke, ki niso bili razumljeni in dobro pripravljeni v skladu z vrsto algoritma ali modela, bodo verjetno ustvarili napačen rezultat, ki ne bo deloval na dan za dnem.
To je eden od razlogov, zakaj je raziskovanje, razumevanje podatkov in delovanje izbranega modela tako pomembno. S tem se lahko izognemo vlaganju smeti v naš model – namesto tega dodamo vrednost vanj in pridobimo vrednost ven.
Vizualizacija podatkov
Do zdaj smo imeli z opisno statistiko nekoliko abstrakten posnetek nekaterih lastnosti podatkov. Drug pomemben korak je vizualizacija in potrditev naše hipoteze o visoki varianci, amplitudi in odstopanjih. Če želite videti, ali se to, kar smo do sedaj opazili, kaže v podatkih, lahko narišemo nekaj grafov.
Zanimivo je tudi videti, kako se značilnosti nanašajo na dva razreda, ki bosta predvidena. Če želite to narediti, uvozimo seaborn
pakirajte in uporabite pairplot
graf, da si ogledate vsako porazdelitev funkcij in vsako ločitev razreda na funkcijo:
import seaborn as sns
sns.pairplot(data=df, hue='Class')
Opomba: Zagon zgornje kode lahko traja nekaj časa, saj parna ploskev združuje raztresene ploskve vseh funkcij (lahko) in prikaže tudi porazdelitve funkcij.
Če pogledamo graf parov, lahko vidimo, da so v večini primerov točke na Çerçevelik
razreda so jasno ločeni od točk Ürgüp Sivrisi
razred. Bodisi so točke enega razreda na desni, medtem ko so druge na levi, ali pa so nekatere navzgor, druge pa navzdol. Če bi za ločevanje razredov uporabili nekakšno krivuljo ali črto, to kaže, da jih je lažje ločiti, če bi bili mešani, bi bila klasifikacija težja naloga.
v Eccentricity
, Compactness
in Aspect_Ration
stolpcev, je zlahka opaziti tudi nekatere točke, ki so "izolirane" ali odstopajo od splošnega trenda podatkov – izstopajoče vrednosti.
Ko gledate diagonalo od zgornjega levega do spodnjega desnega dela grafikona, opazite, da so porazdelitve podatkov tudi barvno označene glede na naše razrede. Oblike porazdelitve in razdalja med obema krivuljama sta še en pokazatelj, kako ločljivi sta – čim dlje sta ena od druge, tem bolje. V večini primerov niso prekrivane, kar pomeni, da jih je lažje ločiti, kar prispeva tudi k naši nalogi.
Zaporedoma lahko narišemo tudi škatlaste ploskve vseh spremenljivk z sns.boxplot()
metoda. Večinoma je koristno, da škatle usmerimo vodoravno, tako da so oblike škatlastih ploskev enake oblikam porazdelitve, to lahko naredimo z orient
argument:
sns.boxplot(data=df, orient='h')
V zgornji risbi opazite to Area
in Convex_Area
imajo tako visoko magnitudo v primerjavi z magnitudami drugih stolpcev, da stisnejo druge škatlaste ploskve. Da si lahko ogledamo vse škatlaste ploskve, lahko prilagodimo značilnosti in jih znova narišemo.
Preden to storimo, razumejmo, da če obstajajo vrednosti funkcij, ki so tesno povezane z drugimi vrednostmi, na primer – če obstajajo vrednosti, ki prav tako postanejo večje, ko se povečajo vrednosti drugih funkcij, imamo pozitivna korelacija; ali če obstajajo vrednosti, ki delujejo nasprotno, postanejo manjše, medtem ko se druge vrednosti zmanjšajo, z a negativna korelacija.
To je pomembno preučiti, ker močna razmerja v podatkih lahko pomenijo, da so nekateri stolpci izpeljani iz drugih stolpcev ali imajo podoben pomen kot naš model. Ko se to zgodi, so lahko rezultati modela precenjeni in želimo rezultate, ki so bližje realnosti. Če obstajajo močne korelacije, to tudi pomeni, da lahko zmanjšamo število funkcij in uporabimo manj stolpcev, zaradi česar je model bolj parsimonious.
Opomba: Privzeta korelacija, izračunana z corr()
metoda je Pearsonov korelacijski koeficient. Ta koeficient je naveden, ko so podatki kvantitativni, normalno porazdeljeni, nimajo izstopajočih vrednosti in imajo linearno razmerje.
Druga možnost bi bila izračunati Spearmanov korelacijski koeficient. Spearmanov koeficient se uporablja, kadar so podatki ordinalni, nelinearni, imajo kakršno koli porazdelitev in odstopanja. Upoštevajte, da se naši podatki ne ujemajo povsem s Pearsonovimi ali Spearmanovimi predpostavkami (obstaja tudi več korelacijskih metod, kot je Kendallova). Ker so naši podatki kvantitativni in je za nas pomembno, da izmerimo njihovo linearno razmerje, bomo uporabili Pearsonov koeficient.
Oglejmo si korelacije med spremenljivkami in nato lahko preidemo na predhodno obdelavo podatkov. Izračunali bomo korelacije z corr()
in jih vizualizirajte s Seabornovo heatmap()
. Standardna velikost toplotnega zemljevida je običajno majhna, zato bomo uvozili matplotlib
(splošni mehanizem/knjižnica za vizualizacijo, na katerem je zgrajen Seaborn) in spremenite velikost figsize
:
import matplotlib.pyplot as plt
plt.figure(figsize=(15, 10))
correlations = df.corr()
sns.heatmap(correlations, annot=True)
V tem toplotnem zemljevidu so vrednosti, ki so bližje 1 ali -1, vrednosti, na katere moramo biti pozorni. Prvi primer pomeni visoko pozitivno korelacijo, drugi pa visoko negativno korelacijo. Obe vrednosti, če nista nad 0.8 ali -0.8, bosta koristni za naš logistični regresijski model.
Kadar obstajajo visoke korelacije, kot je tista od 0.99
med Aspec_Ration
in Compactness
, to pomeni, da se lahko odločimo za uporabo le Aspec_Ration
ali samo Compactness
, namesto obeh (saj bi bila skoraj enaka napovedovalci drug drugega). Enako velja za Eccentricity
in Compactness
z -0.98
korelacija, za Area
in Perimeter
z 0.94
korelacija in nekateri drugi stolpci.
Predhodna obdelava podatkov
Ker smo podatke že nekaj časa raziskovali, se lahko lotimo njihove predobdelave. Za zdaj uporabimo vse funkcije za napoved razreda. Ko pridobimo prvi model, osnovno linijo, lahko nato odstranimo nekaj visoko koreliranih stolpcev in ga primerjamo z osnovno linijo.
Stolpci s funkcijami bodo naši X
podatki in stolpec razreda, naš y
ciljni podatki:
y = df['Class']
X = df.drop(columns=['Class'], axis=1)
Pretvarjanje kategoričnih značilnosti v številske značilnosti
Glede našega Class
stolpec – njegove vrednosti niso števila, to pomeni, da jih moramo tudi transformirati. Obstaja veliko načinov za to preobrazbo; tukaj bomo uporabili replace()
način in zamenjati Çerçevelik
do 0
in Ürgüp Sivrisi
do 1
.
y = y.replace('Çerçevelik', 0).replace('Ürgüp Sivrisi', 1)
Upoštevajte preslikavo! Ko berete rezultate iz svojega modela, jih boste želeli vsaj v mislih pretvoriti nazaj ali nazaj v ime razreda za druge uporabnike.
Razdelitev podatkov na vlake in testne nize
V našem raziskovanju smo ugotovili, da je bilo treba funkcije povečati. Če bi skaliranje izvedli zdaj ali na samodejni način, bi vrednosti skalirali s celoto X
in y
. V tem primeru bi se predstavili uhajanje podatkov, saj bi vrednosti nabora, ki bo kmalu nastal, vplivale na skaliranje. Uhajanje podatkov je pogost vzrok za neponovljive rezultate in navidezno visoko zmogljivost modelov ML.
Razmišljanje o skaliranju kaže, da se moramo najprej razdeliti X
in y
podatke naprej v nize za usposabljanje in testiranje ter nato v fit skalar na vadbeni garnituri, ter do preoblikovanje tako vlak in testni nizi (ne da bi preskusni niz kdaj vplival na skalirnik, ki to počne). Za to bomo uporabili Scikit-Learn's train_test_split()
metoda:
from sklearn.model_selection import train_test_split
SEED = 42
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=.25,
random_state=SEED)
Nastavitev test_size=.25
zagotavlja, da uporabljamo 25 % podatkov za testiranje in 75 % za usposabljanje. To bi lahko izpustili, ko je to privzeta razdelitev, vendar je Pythonic način pisanja kode svetuje, da je "eksplicitno bolje kot implicitno".
Opomba: Stavek "eksplicitno je bolje kot implicitno" se nanaša na Zen Pythonaali PEP20. Predstavlja nekaj predlogov za pisanje kode Python. Če se ti predlogi upoštevajo, se koda upošteva Pythonic. Lahko izveste več o tem tukaj.
Po razdelitvi podatkov na nize za usposabljanje in teste je dobro pogledati, koliko zapisov je v vsakem nizu. To je mogoče storiti z shape
atribut:
X_train.shape, X_test.shape, y_train.shape, y_test.shape
To prikaže:
((1875, 12), (625, 12), (1875,), (625,))
Vidimo lahko, da imamo po razdelitvi 1875 zapisov za usposabljanje in 625 za testiranje.
Podatki o skaliranju
Ko imamo pripravljene nabore za usposabljanje in teste, lahko nadaljujemo s skaliranjem podatkov s Scikit-Learn StandardScaler
objekt (ali drugi skalirniki, ki jih ponuja knjižnica). Da bi preprečili puščanje, je skaler nameščen na X_train
podatki in vrednosti vlaka se nato uporabijo za skaliranje – ali transformacijo – tako podatkov vlaka kot testa:
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
Ker boste običajno poklicali:
scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)
Prvi dve vrstici se lahko strneta z ednino fit_transform()
call, ki se prilega skalerju na setu in ga preoblikuje v enem zamahu. Zdaj lahko reproduciramo škatlaste grafe, da vidimo razliko po skaliranju podatkov.
Glede na to, da skaliranje odstrani imena stolpcev, lahko pred izrisom organiziramo podatke o vlaku v podatkovni okvir z imeni stolpcev, da olajšamo vizualizacijo:
column_names = df.columns[:12]
X_train = pd.DataFrame(X_train, columns=column_names)
sns.boxplot(data=X_train, orient='h')
Končno lahko vidimo vse naše škatle! Upoštevajte, da imajo vsi izstopajoče vrednosti in značilnosti, ki predstavljajo porazdelitev, ki je bolj oddaljena od normalne (ki imajo krivulje nagnjene v levo ali desno), kot npr. Solidity
, Extent
, Aspect_Ration
in Compactedness
, so enaki, ki so imeli višje korelacije.
Odstranjevanje izstopajočih vrednosti z metodo IQR
Vemo že, da lahko na logistično regresijo vplivajo odstopanja. Eden od načinov njihovega zdravljenja je uporaba metode, imenovane Interkvartilni razpon or I.Q.R.. Začetni korak metode IQR je razdelitev naših podatkov o vlaku na štiri dele, imenovane kvartili. Prvi kvartil, Q1, znaša 25 % podatkov, drugo, Q2, do 50 %, tretji, Q3, na 75 % in zadnji, Q4, na 100 %. Polja v škatli so definirana z metodo IQR in so njena vizualna predstavitev.
Če upoštevamo vodoravni okvir, navpična črta na levi označuje 25 % podatkov, navpična črta na sredini 50 % podatkov (ali mediano) in zadnja navpična črta na desni 75 % podatkov. . Bolj enakomerna kot sta oba kvadrata, definirana z navpičnimi črtami – ali bolj ko je srednja navpična črta na sredini – pomeni, da so naši podatki bližje normalni porazdelitvi ali manj poševni, kar je koristno za našo analizo.
Poleg škatle IQR so na obeh straneh tudi vodoravne črte. Te vrstice označujejo najmanjšo in največjo vrednost porazdelitve, ki jo definira
$$
Najmanj = Q1 – 1.5*IQR
$$
in
$$
Največ = Q3 + 1.5*IQR
$$
IQR je ravno razlika med Q3 in Q1 (ali Q3 – Q1) in je najbolj osrednja točka podatkov. Zato pri iskanju IQR na koncu filtriramo izstopajoče vrednosti v skrajnih podatkih ali v točkah minimuma in maksimuma. Škatlaste ploskve nam dajejo kratek vpogled v to, kakšen bo rezultat metode IQR.
Lahko uporabimo Pande quantile()
metoda za iskanje naših kvantilov in iqr
Iz scipy.stats
paket za pridobitev interkvartilnega obsega podatkov za vsak stolpec:
from scipy.stats import iqr
Q1 = X_train.quantile(q=.25)
Q3 = X_train.quantile(q=.75)
IQR = X_train.apply(iqr)
Zdaj imamo Q1, Q3 in IQR, lahko filtriramo vrednosti bližje mediani:
minimum = X_train < (Q1-1.5*IQR)
maximum = X_train > (Q3+1.5*IQR)
filter = ~(minimum | maximum).any(axis=1)
X_train = X_train[filter]
Po filtriranju vrstic za usposabljanje lahko vidimo, koliko jih je še v podatkih shape
:
X_train.shape
Rezultat tega je:
(1714, 12)
Vidimo lahko, da se je število vrstic po filtriranju povečalo s 1875 na 1714. To pomeni, da je 161 vrstic vsebovalo izstopajoče vrednosti ali 8.5 % podatkov.
Opomba: Priporočljivo je, da filtriranje izstopajočih vrednosti, odstranitev vrednosti NaN in druga dejanja, ki vključujejo filtriranje in čiščenje podatkov, ostanejo pod ali do 10 % podatkov. Poskusite razmisliti o drugih rešitvah, če vaše filtriranje ali odstranjevanje presega 10 % vaših podatkov.
Po odstranitvi izstopajočih vrednosti smo skoraj pripravljeni na vključitev podatkov v model. Za prilagoditev modela bomo uporabili podatke o vlaku. X_train
se filtrira, kaj pa y_train
?
y_train.shape
To ustvari:
(1875,)
To opazite y_train
še vedno ima 1875 vrstic. Ujemati se moramo s številom y_train
vrstic na število X_train
vrstice in ne samo poljubno. Odstraniti moramo y-vrednosti primerkov bučnih semen, ki smo jih odstranili in so verjetno razpršeni po y_train
set. Filtrirano X_train
stil ima svoje prvotne indekse in indeks ima vrzeli, kjer smo odstranili odstopanja! Nato lahko uporabimo indeks X_train
DataFrame za iskanje ustreznih vrednosti y_train
:
y_train = y_train.iloc[X_train.index]
Ko to storimo, si lahko ogledamo y_train
ponovno oblikuj:
y_train.shape
Kateri izhodi:
(1714,)
Oglejte si naš praktični, praktični vodnik za učenje Gita z najboljšimi praksami, standardi, sprejetimi v panogi, in priloženo goljufijo. Nehajte Googlati ukaze Git in pravzaprav naučiti it!
zdaj, y_train
ima tudi 1714 vrstic in so enake kot X_train
vrstice. Končno smo pripravljeni ustvariti naš logistični regresijski model!
Implementacija modela logistične regresije
Najtežji del je končan! Predhodna obdelava je običajno težja od razvoja modela, ko gre za uporabo knjižnic, kot je Scikit-Learn, ki je poenostavila uporabo modelov ML na le nekaj vrsticah.
Najprej uvozimo LogisticRegression
in ga instancirajte, tako da ustvarite a LogisticRegression
predmet:
from sklearn.linear_model import LogisticRegression
logreg = LogisticRegression(random_state=SEED)
Drugič, naše podatke o vlaku prilagodimo logreg
model z fit()
metodo in napovedati naše testne podatke z predict()
metoda, ki shranjuje rezultate kot y_pred
:
logreg.fit(X_train.values, y_train)
y_pred = logreg.predict(X_test)
Z našim modelom smo že naredili napovedi! Poglejmo prve 3 vrstice v X_train
da vidite, katere podatke smo uporabili:
X_train[:3]
Zgornja koda izpiše:
Area Perimeter Major_Axis_Length Minor_Axis_Length Convex_Area Equiv_Diameter Eccentricity Solidity Extent Roundness Aspect_Ration Compactness
0 -1.098308 -0.936518 -0.607941 -1.132551 -1.082768 -1.122359 0.458911 -1.078259 0.562847 -0.176041 0.236617 -0.360134
1 -0.501526 -0.468936 -0.387303 -0.376176 -0.507652 -0.475015 0.125764 0.258195 0.211703 0.094213 -0.122270 0.019480
2 0.012372 -0.209168 -0.354107 0.465095 0.003871 0.054384 -0.453911 0.432515 0.794735 0.647084 -0.617427 0.571137
In pri prvih 3 napovedih v y_pred
za ogled rezultatov:
y_pred[:3]
Rezultat tega je:
array([0, 0, 0])
Za te tri vrste so bile naše napovedi, da so bila semena prvega razreda, Çerçevelik
.
z logistična regresija, namesto napovedi končnega razreda, kot npr 0
, lahko tudi napovemo verjetnost, da se vrstica nanaša na 0
razred. To se dejansko zgodi, ko logistična regresija razvrsti podatke in predict()
metoda nato prenese to napoved skozi prag, da vrne "trdi" razred. Če želite napovedati verjetnost, da pripadate razredu, predict_proba()
se uporablja:
y_pred_proba = logreg.predict_proba(X_test)
Oglejmo si tudi prve 3 vrednosti napovedi verjetnosti y:
y_pred_proba[:3]
Kateri izhodi:
# class 0 class 1
array([[0.54726628, 0.45273372],
[0.56324527, 0.43675473],
[0.86233349, 0.13766651]])
Zdaj imamo namesto treh ničel en stolpec za vsak razred. V stolpcu na levi, začenši z 0.54726628
, so verjetnosti podatkov, ki se nanašajo na razred 0
; in v desnem stolpcu, začenši z 0.45273372
, so verjetnost, da se nanaša na razred 1
.
Opomba: Ta razlika v klasifikaciji je znana tudi kot težko in mehko napoved. Trdo predvidevanje zaokroži napoved v razred, mehko predvidevanje pa izpiše verjetnost primerka, ki pripada razredu.
Obstaja več informacij o tem, kako je bil narejen predvideni rezultat. Pravzaprav ni bilo 0
, vendar 55-odstotna možnost za razred 0
, in 45-odstotno možnost za razred 1
. To se kaže kot prvi trije X_test
podatkovne točke, ki se nanašajo na razred 0
, so resnično jasni le glede tretje podatkovne točke, s 86-odstotno verjetnostjo – in ne toliko za prvi dve podatkovni točki.
Pri sporočanju ugotovitev z uporabo metod ML – običajno je najbolje vrniti mehki razred in povezano verjetnost kot “zaupanje” te klasifikacije.
Več o tem, kako se to izračuna, bomo govorili, ko se poglobimo v model. V tem času lahko nadaljujemo z naslednjim korakom.
Vrednotenje modela s poročili o klasifikaciji
Tretji korak je videti, kako se model obnese na testnih podatkih. Scikit-Learn lahko uvozimo classification_report()
in mimo našega y_test
in y_pred
kot argumenti. Po tem lahko natisnemo njegov odgovor.
Klasifikacijsko poročilo vsebuje najbolj uporabljene klasifikacijske metrike, kot npr natančnost, odpoklic, f1-rezultatin natančnost.
- Precision: razumeti, katere pravilne vrednosti napovedi je naš klasifikator štel za pravilne. Natančnost bo te prave pozitivne vrednosti razdelila na vse, kar je bilo predvideno kot pozitivno:
$$
natančnost = frac{text{true positive}}{text{true positive} + text{false positive}}
$$
- Recall: razumeti, koliko resničnih pozitivnih rezultatov je prepoznal naš klasifikator. Odpoklic se izračuna tako, da se resnični pozitivni učinki delijo s čimer koli, kar bi bilo predvideno kot pozitivno:
$$
odpoklic = frac{besedilo{resnično pozitivno}}{besedilo{resnično pozitivno} + besedilo{lažno negativno}}
$$
- Ocena F1: je uravnotežena oz harmonično srednjo vrednost natančnosti in odpoklica. Najnižja vrednost je 0, najvišja pa 1. Kdaj
f1-score
je enako 1, to pomeni, da so bili vsi razredi pravilno predvideni – to rezultat je zelo težko dobiti z resničnimi podatki:
$$
besedilo{f1-rezultat} = 2* frac{besedilo{natančnost} * besedilo{priklic}}{besedilo{natančnost} + besedilo{priklic}}
$$
- natančnost: opisuje, koliko napovedi je imel naš klasifikator pravilnih. Najnižja vrednost natančnosti je 0, najvišja pa 1. To vrednost običajno pomnožimo s 100, da dobimo odstotek:
$$
natančnost = frac{besedilo{število pravilnih napovedi}}{besedilo{skupno število napovedi}}
$$
Opomba: Izjemno težko je doseči 100-odstotno natančnost pri kakršnih koli resničnih podatkih. Če se to zgodi, se zavedajte, da morda prihaja do uhajanja ali kaj narobe – ni soglasja o idealni vrednosti natančnosti in je tudi odvisna od konteksta. Vrednost 70 %, kar pomeni, da se bo klasifikator zmotil pri 30 % podatkov ali nad 70 %, običajno zadostuje za večino modelov.
from sklearn.metrics import classification_report
cr = classification_report(y_test, y_pred)
print(cr)
Nato si lahko ogledamo rezultat klasifikacijskega poročila:
precision recall f1-score support
0 0.83 0.91 0.87 316
1 0.90 0.81 0.85 309
accuracy 0.86 625
macro avg 0.86 0.86 0.86 625
weighted avg 0.86 0.86 0.86 625
To je naš rezultat. Upoštevajte to precision
, recall
, f1-score
in accuracy
vse meritve so zelo visoke, nad 80 %, kar je idealno – vendar so na te rezultate verjetno vplivale visoke korelacije in se dolgoročno ne bodo ohranile.
Natančnost modela je 86 %, kar pomeni, da se v 14 % primerov zmoti pri klasifikaciji. Imamo te splošne informacije, vendar bi bilo zanimivo vedeti, ali se 14% napak zgodi pri razvrščanju razreda 0
ali razred 1
. Da ugotovimo, kateri razredi so napačno identificirani kot kateri in v kateri pogostosti – lahko izračunamo in narišemo matrika zmede napovedi našega modela.
Vrednotenje modela z matriko zmede
Izračunajmo in nato narišimo matriko zmede. Ko to storimo, lahko razumemo vsak del tega. Za izris matrike zmede bomo uporabili Scikit-Learn confusion_matrix()
, ki jih bomo uvozili iz metrics
modul.
Matriko zmede je lažje vizualizirati z uporabo Seaborna heatmap()
. Ko jo ustvarimo, bomo našo matriko zmede posredovali kot argument za toplotni zemljevid:
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, y_pred)
sns.heatmap(cm, annot=True, fmt='d')
- Matrica zmede: matrika prikazuje, koliko vzorcev je model dobil pravilnih ali napačnih za vsak razred. Pokličemo vrednosti, ki so bile pravilne in pravilno napovedane resnično pozitivni, in tisti, ki so bili napovedani kot pozitivni, vendar niso bili pozitivni, se imenujejo lažno pozitivno. Ista nomenklatura prave negative in lažno negativnih uporablja se za negativne vrednosti;
Če pogledamo graf matrike zmede, lahko vidimo, da imamo 287
vrednote, ki so bile 0
in napovedal kot 0
- ali resnično pozitivni za razred 0
(semena Çerçevelik). Tudi imamo 250
resnično pozitivno za razred 1
(semena Ürgüp Sivrisi). Pravi pozitivi se vedno nahajajo v matrični diagonali, ki gre od zgornjega levega do spodnjega desnega.
Prav tako imajo 29
vrednote, ki naj bi bile 0
, ampak napovedali kot 1
(lažno pozitivno) in 59
vrednote, ki so bile 1
in napovedal kot 0
(lažno negativnih). S temi številkami lahko razumemo, da je največja napaka modela ta, da napove napačno negativne rezultate. Tako lahko seme Ürgüp Sivrisi večinoma razvrstimo kot seme Çerçevelik.
Tovrstno napako pojasnjuje tudi 81-odstotni priklic razreda 1
. Opazite, da so metrike povezane. In razlika v odpoklicu izhaja iz tega, da imamo 100 vzorcev manj razreda Ürgüp Sivrisi. To je ena od posledic le nekaj vzorcev manj kot v drugem razredu. Za nadaljnje izboljšanje priklica lahko eksperimentirate z utežmi razreda ali uporabite več vzorcev Ürgüp Sivrisi.
Doslej smo izvedli večino tradicionalnih korakov podatkovne znanosti in uporabili model logistične regresije kot črno skrinjico.
Opomba: Če želite iti dlje, uporabite Navzkrižno preverjanje (CV) in iskanje po mreži iskati model, ki glede podatkov najbolj posplošuje, in najboljše parametre modela, ki so izbrani pred treningom oz. hiperparametrov.
V idealnem primeru bi lahko z življenjepisom in iskanjem po mreži implementirali povezan način izvajanja korakov predhodne obdelave podatkov, razdelitve podatkov, modeliranja in vrednotenja – kar je enostavno s Scikit-Learnom. cevovodov.
Zdaj je čas, da odpremo črno skrinjico in pogledamo vanjo, da se poglobimo v razumevanje delovanja logistične regresije.
Poglabljamo se v resnično delovanje logistične regresije
O regresija Beseda ni naključna, da bi razumeli, kaj počne logistična regresija, se lahko spomnimo, kaj njen sorodnik, linearna regresija, naredi s podatki. Formula linearne regresije je bila naslednja:
$$
y = b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + pike + b_n * x_n
$$
V kateri b0 je bil regresijski presek, b1 koeficient in x1 podatki.
Ta enačba je povzročila ravno črto, ki je bila uporabljena za napovedovanje novih vrednosti. Če se spomnimo uvoda, je zdaj razlika v tem, da ne bomo napovedovali novih vrednosti, ampak razred. Torej je treba to ravno črto spremeniti. Z logistično regresijo uvedemo nelinearnost in napoved se zdaj izvaja s pomočjo krivulje namesto črte:
Upoštevajte, da medtem ko linija linearne regresije poteka naprej in je sestavljena iz neprekinjenih neskončnih vrednosti, lahko krivuljo logistične regresije razdelimo na sredino in ima ekstreme v vrednosti 0 in 1. Ta oblika črke »S« je razlog, da razvršča podatke – točke, ki so bližje ali padejo na najvišjo skrajnost, spadajo v razred 1, medtem ko točke, ki so v spodnjem kvadrantu ali bližje 0, spadajo v razred 0. Sredina "S" je sredina med 0 in 1, 0.5 - je prag za logistične regresijske točke.
Vizualno razliko med logistično in linearno regresijo že razumemo, kaj pa formula? Formula za logistično regresijo je naslednja:
$$
y = b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + pike + b_n * x_n
$$
Lahko se zapiše tudi kot:
$$
y_{prob} = frac{1}{1 + e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}
$$
Ali celo zapisano kot:
$$
y_{prob} = frac{e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}{1 + e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + pike + b_n * x_n)}}
$$
V zgornji enačbi imamo verjetnost vnosa namesto njegove vrednosti. Ima 1 kot števec, tako da lahko povzroči vrednost med 0 in 1, in 1 plus vrednost v imenovalcu, tako da je njegova vrednost 1 in nekaj – to pomeni, da rezultat celotnega ulomka ne more biti večji od 1 .
In kakšna je vrednost, ki je v imenovalcu? je e, osnova naravnega logaritma (približno 2.718282), dvignjena na potenco linearne regresije:
$$
e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + pike + b_n * x_n)}
$$
Drug način pisanja bi bil:
$$
Levo (frac{p}{1-p} desno) = {(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$
V zadnji enačbi ln je naravni logaritem (osnova e) in p je verjetnost, zato je logaritem verjetnosti rezultata enak rezultatu linearne regresije.
Z drugimi besedami, z rezultatom linearne regresije in naravnim logaritmom lahko pridemo do verjetnosti, da se vnos nanaša ali ne na zasnovani razred.
Celoten postopek izpeljave logistične regresije je naslednji:
$$
p{X} = frac{e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}{1 + e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + pike + b_n * x_n)}}
$$
$$
p(1 + e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}) = e^{(b_0 + b_1 * x_1 + b_2 *x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$
$$
p + p*e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)} = e^{(b_0 + b_1 * x_1 + b_2 *x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$
p
=
e
(
b
0
+
b
1
*
x
1
+
b
2
*
x
2
+
b
3
*
x
3
+
...
+
b
n
*
x
n
)
-
p
*
e
(
b
0
+
b
1
*
x
1
+
b
2
*
x
2
+
b
3
*
x
3
+
...
+
b
n
*
x
n
)
$$
frac{p}{1-p} = e^{(b_0 + b_1 * x_1 + b_2 *x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$
$$
Levo (frac{p}{1-p} desno) = (b_0 + b_1 * x_1 + b_2 *x_2 + b_3 * x_3 + ldots + b_n * x_n)
$$
To pomeni, da ima model logistične regresije tudi koeficiente in vrednost preseka. Ker uporablja linearno regresijo in ji doda nelinearno komponento z naravnim logaritmom (e
).
Vrednosti koeficientov in preseka našega modela lahko vidimo na enak način kot pri linearni regresiji z uporabo coef_
in intercept_
lastnosti:
logreg.coef_
Ki prikazuje koeficiente vsake od 12 lastnosti:
array([[ 1.43726172, -1.03136968, 0.24099522, -0.61180768, 1.36538261,
-1.45321951, -1.22826034, 0.98766966, 0.0438686 , -0.78687889,
1.9601197 , -1.77226097]])
logreg.intercept_
Posledica tega je:
array([0.08735782])
S koeficienti in presečnimi vrednostmi lahko izračunamo predvidene verjetnosti naših podatkov. Dobimo prvo X_test
spet vrednosti, kot primer:
X_test[:1]
To vrne prvo vrstico X_test
kot niz NumPy:
array([[-1.09830823, -0.93651823, -0.60794138, -1.13255059, -1.0827684 ,
-1.12235877, 0.45891056, -1.07825898, 0.56284738, -0.17604099,
0.23661678, -0.36013424]])
Po začetni enačbi:
$$
p{X} = frac{e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}{1 + e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + pike + b_n * x_n)}}
$$
V pythonu imamo:
import math
lin_reg = logreg.intercept_[0] +
((logreg.coef_[0][0]* X_test[:1][0][0])+
(logreg.coef_[0][1]* X_test[:1][0][1])+
(logreg.coef_[0][2]* X_test[:1][0][2])+
(logreg.coef_[0][3]* X_test[:1][0][3])+
(logreg.coef_[0][4]* X_test[:1][0][4])+
(logreg.coef_[0][5]* X_test[:1][0][5])+
(logreg.coef_[0][6]* X_test[:1][0][6])+
(logreg.coef_[0][7]* X_test[:1][0][7])+
(logreg.coef_[0][8]* X_test[:1][0][8])+
(logreg.coef_[0][9]* X_test[:1][0][9])+
(logreg.coef_[0][10]* X_test[:1][0][10])+
(logreg.coef_[0][11]* X_test[:1][0][11]))
px = math.exp(lin_reg)/(1 +(math.exp(lin_reg)))
px
Rezultat tega je:
0.45273372469369133
Če ponovno pogledamo na predict_proba
rezultat prvega X_test
line, imamo:
logreg.predict_proba(X_test[:1])
To pomeni, da izvirna logistična regresijska enačba poda verjetnost vnosa glede na razred 1
, da ugotovite, katera verjetnost je za razred 0
, lahko preprosto:
1 - px
Upoštevajte, da oboje px
in 1-px
so enaki predict_proba
rezultate. Tako se izračuna logistična regresija in zakaj regresija je del njegovega imena. Kaj pa izraz logistično?
Izraz logistično prihaja iz logit, kar je funkcija, ki smo jo že videli:
$$
Levo (frac{p}{1-p} desno)
$$
Pravkar smo ga izračunali z px
in 1-px
. To je logit, imenovan tudi log-odds ker je enak logaritmu kvot, kjer je p
je verjetnost.
zaključek
V tem priročniku smo preučevali enega najbolj temeljnih klasifikacijskih algoritmov strojnega učenja, tj logistična regresija.
Sprva smo logistično regresijo izvajali kot črno skrinjico s knjižnico strojnega učenja Scikit-Learn, kasneje pa smo jo razumeli korak za korakom, da smo imeli jasno, zakaj in od kod prihajata izraza regresija in logistika.
Prav tako smo raziskali in preučili podatke, pri čemer smo razumeli, da je to eden najpomembnejših delov analize podatkovne znanosti.
Od tu naprej bi vam svetoval, da se malo poigrate večrazredna logistična regresija, logistična regresija za več kot dva razreda – lahko uporabite isti algoritem logistične regresije za druge nize podatkov, ki imajo več razredov, in interpretirate rezultate.
Opomba: Na voljo je dobra zbirka naborov podatkov tukaj za igranje z vami.
Prav tako bi vam svetoval, da preučite L1 in L2 ureditve, so način za »kaznovanje« višjih podatkov, da bi se približali normalnim, ki ohranjajo kompleksnost modela, tako da lahko algoritem doseže boljši rezultat. Izvedba Scikit-Learn, ki smo jo uporabili, že ima privzeto ureditev L2. Druga stvar, na katero je treba gledati, je drugačnost reševalci, Kot je lbgs
, ki optimizirajo delovanje algoritma logistične regresije.
Pomembno je tudi, da si ogledate Statistično pristop k logistični regresiji. Ima predpostavke o obnašanju podatkov in o drugih statističnih podatkih, ki morajo veljati za zagotavljanje zadovoljivih rezultatov, kot so:
- opazovanja so neodvisna;
- med pojasnjevalnimi spremenljivkami ni multikolinearnosti;
- ni ekstremnih odstopanj;
- obstaja linearna povezava med pojasnjevalnimi spremenljivkami in logit spremenljivke odziva;
- je vzorec dovolj velik.
Opazite, koliko teh predpostavk je bilo že zajetih v naši analizi in obdelavi podatkov.
Upam, da še naprej raziskujete, kaj ponuja logistična regresija v vseh svojih različnih pristopih!
- blockchain
- C + +
- Koda
- coingenius
- znanost o podatkih
- vizualizacija podatkov
- Java
- matplotlib
- nezamenljiv žeton
- otopeli
- OpenSea
- pand
- PHP
- platon
- platon ai
- Platonova podatkovna inteligenca
- Igra Platon
- Platoblockchain
- PlatoData
- platogaming
- poligon
- Python
- Reagirajo
- scikit-učiti
- morski rojen
- pametna pogodba
- Solana
- Stackabuse
- Vyper
- Web3
- zefirnet