Ghid definitiv pentru regresia logistică în Python PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

Ghid definitiv pentru regresia logistică în Python

Introducere

Uneori confundat cu regresie liniara de către novici – datorită împărtășirii termenului regres - regresie logistică este mult diferit de regresie liniara. În timp ce regresia liniară prezice valori precum 2, 2.45, 6.77 sau valori continue, făcându-l un regres algoritm, regresie logistică prezice valori precum 0 sau 1, 1 sau 2 sau 3, care sunt valori discrete, făcându-l un clasificare algoritm. Da, se numește regres dar este o clasificare algoritm. Mai multe despre asta într-o clipă.

Prin urmare, dacă problema dvs. de știință a datelor implică valori continue, puteți aplica a regres algoritm (regresia liniară este una dintre ele). În caz contrar, dacă implică clasificarea intrărilor, a valorilor discrete sau a claselor, puteți aplica o clasificare algoritm (regresia logistică este una dintre ele).

În acest ghid, vom efectua regresia logistică în Python cu biblioteca Scikit-Learn. Vom explica, de asemenea, de ce cuvântul „regresie” este prezent în nume și cum funcționează regresia logistică.

Pentru a face acest lucru, vom încărca mai întâi date care vor fi clasificate, vizualizate și preprocesate. Apoi, vom construi un model de regresie logistică care va înțelege aceste date. Acest model va fi apoi evaluat și folosit pentru a prezice valori pe baza noilor intrări.

motivaţia

Compania pentru care lucrezi a făcut un parteneriat cu o fermă agricolă turcească. Acest parteneriat presupune vânzarea semințelor de dovleac. Semințele de dovleac sunt foarte importante pentru alimentația umană. Conțin o proporție bună de carbohidrați, grăsimi, proteine, calciu, potasiu, fosfor, magneziu, fier și zinc.

În echipa de știință a datelor, sarcina ta este să faci diferența dintre tipurile de semințe de dovleac doar folosind date - sau clasificator datele în funcție de tipul de sămânță.

Ferma turcească lucrează cu două tipuri de semințe de dovleac, unul se numește Çerçevelik si celalalt Ürgüp Sivrisi.

Pentru a clasifica semințele de dovleac, echipa ta a urmat lucrarea din 2021 „Utilizarea metodelor de învățare automată în clasificarea semințelor de dovleac (Cucurbita pepo L.). Resursele genetice și evoluția culturilor” de la Koklu, Sargil și Ozbek – în această lucrare, există o metodologie pentru fotografiarea și extragerea măsurătorilor semințelor din imagini.

După finalizarea procesului descris în lucrare, au fost extrase următoarele măsurători:

  • Zonă – numărul de pixeli din limitele unei semințe de dovleac
  • Perimetru – circumferința în pixeli a unei semințe de dovleac
  • Lungimea axei majore – de asemenea circumferința în pixeli a unei semințe de dovleac
  • Lungimea axei minore – distanța pe axa mică a unei semințe de dovleac
  • Excentricitate – excentricitatea unei semințe de dovleac
  • Zona convexa – numărul de pixeli ai celei mai mici coji convexe la regiunea formată de sămânța de dovleac
  • Măsură – raportul dintre suprafața unei semințe de dovleac și pixelii casetei de delimitare
  • Diametru echivalent – rădăcina pătrată a înmulțirii ariei semințelor de dovleac cu patru împărțită la pi
  • soliditate – proporția suprafeței semințelor de dovleac față de aria cercului cu aceeași circumferință
  • trăinicie – starea convexă și convexă a semințelor de dovleac
  • Rotunjime – ovalitatea semințelor de dovleac fără a lua în considerare distorsiunile marginilor acestuia
  • Raportul de aspect – raportul de aspect al semintelor de dovleac

Acestea sunt măsurătorile cu care trebuie să lucrați. Pe langa masuratori, mai exista si Clasă etichetă pentru cele două tipuri de semințe de dovleac.

Pentru a începe să clasificăm semințele, să importăm datele și să începem să le privim.

Înțelegerea setului de date

Notă: Puteți descărca setul de date pentru dovleac aici.

După descărcarea setului de date, îl putem încărca într-o structură de cadru de date folosind pandas bibliotecă. Deoarece este un fișier Excel, vom folosi fișierul read_excel() metodă:

import pandas as pd

fpath = 'dataset/pumpkin_seeds_dataset.xlsx' 
df = pd.read_excel(fpath)

Odată ce datele sunt încărcate, putem arunca o privire rapidă la primele 5 rânduri folosind head() metodă:

df.head() 

Rezultă:

	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

Aici, avem toate măsurătorile în coloanele lor respective, noastre caracteristici, și de asemenea Clasă coloana, nostru ţintă, care este ultimul din cadrul de date. Putem vedea câte măsurători avem folosind shape atribut:

df.shape 

Rezultatul este:

(2500, 13)

Rezultatul formei ne spune că există 2500 de intrări (sau rânduri) în setul de date și 13 coloane. Deoarece știm că există o coloană țintă - asta înseamnă că avem 12 coloane de caracteristici.

Acum putem explora variabila țintă, sămânța de dovleac Class. Deoarece vom prezice acea variabilă, este interesant să vedem câte mostre din fiecare sămânță de dovleac avem. De obicei, cu cât diferența dintre numărul de instanțe din clasele noastre este mai mică, cu atât eșantionul nostru este mai echilibrat și predicțiile noastre sunt mai bune.

Această inspecție se poate face prin numărarea fiecărei probe de semințe cu value_counts() metodă:

df['Class'].value_counts() 

Codul de mai sus afișează:

Çerçevelik       1300
Ürgüp Sivrisi    1200
Name: Class, dtype: int64

Putem vedea că există 1300 de mostre ale Çerçevelik sămânță și 1200 de mostre de Ürgüp Sivrisi sămânță. Observați că diferența dintre ele este de 100 de mostre, o diferență foarte mică, ceea ce este bun pentru noi și indică că nu este nevoie să reechilibrați numărul de mostre.

Să ne uităm și la statisticile descriptive ale caracteristicilor noastre cu describe() metoda pentru a vedea cât de bine sunt distribuite datele. Vom transpune și tabelul rezultat cu T pentru a facilita compararea între statistici:

df.describe().T

Tabelul rezultat este:

					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

Privind la tabel, când comparăm însemna și deviație standard (std), se poate observa că majoritatea caracteristicilor au o medie care este departe de abaterea standard. Aceasta indică faptul că valorile datelor nu sunt concentrate în jurul valorii medii, ci mai împrăștiate în jurul acesteia - cu alte cuvinte, au variabilitate mare.

De asemenea, când se uită la minim (min) Şi maxim (max) coloane, unele caracteristici, cum ar fi Area, și Convex_Area, au diferențe mari între valorile minime și maxime. Aceasta înseamnă că acele coloane au date foarte mici și, de asemenea, valori de date foarte mari, sau amplitudine mai mare între valorile datelor.

Cu variabilitate mare, amplitudine mare și caracteristici cu unități de măsură diferite, majoritatea datelor noastre ar beneficia de aceeași scară pentru toate caracteristicile sau de a fi scalate. Scalarea datelor va centra datele în jurul mediei și va reduce varianța acesteia.

Acest scenariu indică probabil și faptul că există valori aberante și valori extreme în date. Deci, cel mai bine este să aveți câteva tratament anormal pe lângă scalarea datelor.

Există unii algoritmi de învățare automată, de exemplu, algoritmi bazați pe arbore, cum ar fi Clasificarea aleatorie a pădurilor, care nu sunt afectate de variația mare a datelor, valori aberante și valori extreme. Regresie logistică este diferit, se bazează pe o funcție care ne clasifică valorile, iar parametrii acelei funcții pot fi afectați de valori care sunt în afara trendului general al datelor și au varianță mare.

Vom înțelege mai multe despre regresia logistică într-un pic când vom ajunge să o implementăm. Deocamdată, putem continua să ne explorăm datele.

Notă: Există o vorbă populară în informatică: „Gunoi înăuntru, gunoi afară” (GIGO), care este potrivit pentru învățarea automată. Aceasta înseamnă că atunci când avem date de gunoi – măsurători care nu descriu fenomenele în sine, date care nu au fost înțelese și bine pregătite în funcție de tipul de algoritm sau model, vor genera probabil o ieșire incorectă care nu va funcționa. de la o zi la alta.
Acesta este unul dintre motivele pentru care explorarea, înțelegerea datelor și modul în care funcționează modelul ales sunt atât de importante. Făcând asta, putem evita să punem gunoi în modelul nostru – să-i punem valoare în schimb și să scoatem valoare.

Vizualizarea datelor

Până acum, cu statisticile descriptive, avem un instantaneu oarecum abstract al unor calități ale datelor. Un alt pas important este să îl vizualizăm și să confirmăm ipoteza noastră de varianță mare, amplitudine și valori aberante. Pentru a vedea dacă ceea ce am observat până acum arată în date, putem reprezenta niște grafice.

De asemenea, este interesant de văzut cum se leagă caracteristicile cu cele două clase care vor fi prezise. Pentru a face asta, să importăm fișierul seaborn ambalați și utilizați pairplot grafic pentru a analiza fiecare distribuție de caracteristici și fiecare separare de clasă per caracteristică:

import seaborn as sns


sns.pairplot(data=df, hue='Class')

Notă: Rularea codului de mai sus poate dura ceva timp, deoarece diagrama de perechi combină graficele de dispersie ale tuturor caracteristicilor (se poate) și afișează, de asemenea, distribuțiile caracteristicilor.

Privind la diagrama de perechi, putem vedea că, în majoritatea cazurilor, punctele Çerçevelik clasa sunt clar separate de punctele Ürgüp Sivrisi clasă. Fie punctele unei clase sunt la dreapta când celelalte sunt la stânga, fie unele sunt în sus în timp ce celelalte sunt în jos. Dacă ar fi să folosim un fel de curbă sau linie pentru a separa clasele, acest lucru arată că este mai ușor să le separăm, dacă ar fi amestecate, clasificarea ar fi o sarcină mai grea.

În Eccentricity, Compactness și Aspect_Ration coloane, unele puncte care sunt „izolate” sau care se abat de la tendința generală a datelor – valori aberante – sunt de asemenea ușor de observat.

Când vă uitați la diagonala din stânga sus până în dreapta jos a diagramei, observați că distribuțiile de date sunt, de asemenea, codificate în culori în funcție de clasele noastre. Formele de distribuție și distanța dintre ambele curbe sunt alți indicatori ai cât de separabile sunt – cu cât sunt mai îndepărtate una de cealaltă, cu atât mai bine. În cele mai multe cazuri, ele nu sunt suprapuse, ceea ce înseamnă că sunt mai ușor de separat, contribuind și la sarcina noastră.

În secvență, putem, de asemenea, reprezenta graficul boxplot-urilor tuturor variabilelor cu sns.boxplot() metodă. De cele mai multe ori, este util să orientați boxplot-urile pe orizontală, astfel încât formele boxploturilor sunt aceleași cu formele de distribuție, putem face asta cu orient argument:


sns.boxplot(data=df, orient='h') 

Ghid definitiv pentru regresia logistică în Python PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

În complotul de mai sus, observați că Area și Convex_Area au o magnitudine atât de mare în comparație cu mărimile celorlalte coloane, încât strică celelalte boxplot. Pentru a putea privi toate boxploturile, putem scala caracteristicile și le putem reprezenta din nou.

Înainte de a face asta, să înțelegem doar că, dacă există valori ale caracteristicilor care sunt strâns legate de alte valori, de exemplu, dacă există valori care devin și mai mari atunci când alte valori ale caracteristicilor devin mai mari, având o pozitiv de corespondență; sau dacă există valori care fac opusul, se micșorează în timp ce alte valori se micșorează, având a corelație negativă.

Acest lucru este important de luat în considerare, deoarece existența unor relații puternice în date ar putea însemna că unele coloane au fost derivate din alte coloane sau au o semnificație similară cu modelul nostru. Când se întâmplă acest lucru, rezultatele modelului ar putea fi supraestimate și dorim rezultate mai apropiate de realitate. Dacă există corelații puternice, înseamnă, de asemenea, că putem reduce numărul de caracteristici și putem folosi mai puține coloane, făcând modelul mai mult strângător.

Notă: Corelația implicită calculată cu corr() metoda este Coeficientul de corelație Pearson. Acest coeficient este indicat atunci când datele sunt cantitative, distribuite în mod normal, nu au valori aberante și au o relație liniară.

O altă alegere ar fi să calculezi Coeficientul de corelație al lui Spearman. Coeficientul lui Spearman este utilizat atunci când datele sunt ordinale, neliniare, au orice distribuție și au valori aberante. Observați că datele noastre nu se încadrează în totalitate în ipotezele lui Pearson sau Spearman (există și mai multe metode de corelare, cum ar fi cea a lui Kendall). Deoarece datele noastre sunt cantitative și este important pentru noi să măsurăm relația lor liniară, vom folosi coeficientul Pearson.

Să aruncăm o privire la corelațiile dintre variabile și apoi putem trece la preprocesarea datelor. Vom calcula corelațiile cu corr() metoda și vizualizați-le cu Seaborn's heatmap(). Dimensiunea standard a hărții termice tinde să fie mică, așa că vom importa matplotlib (motor de vizualizare generală/biblioteca pe care Seaborn este construit) și modificați dimensiunea cu figsize:

import matplotlib.pyplot as plt
plt.figure(figsize=(15, 10))

correlations = df.corr()
sns.heatmap(correlations, annot=True) 

Ghid definitiv pentru regresia logistică în Python PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

În această hartă termică, valorile mai apropiate de 1 sau -1 sunt valorile cărora trebuie să fim atenți. Primul caz, denotă o corelație pozitivă ridicată, iar al doilea, o corelație negativă ridicată. Ambele valori, dacă nu sunt peste 0.8 sau -0.8, vor fi benefice pentru modelul nostru de regresie logistică.

Când există corelații mari precum cea de 0.99 între Aspec_Ration și Compactness, aceasta înseamnă că putem alege să folosim numai Aspec_Ration sau numai Compactness, în loc de ambele (deoarece ar fi aproape egale predictori unul de altul). Același lucru este valabil și pentru Eccentricity și Compactness cu -0.98 corelație, pentru Area și Perimeter cu 0.94 corelație și alte câteva coloane.

Preprocesarea Datelor

Deoarece am explorat deja datele pentru o vreme, putem începe să le preprocesăm. Deocamdată, să folosim toate caracteristicile pentru predicția clasei. După obținerea unui prim model, o linie de bază, putem apoi elimina unele dintre coloanele foarte corelate și le putem compara cu linia de bază.

Coloanele de caracteristici vor fi ale noastre X date și coloana de clasă, nostru y date țintă:

y = df['Class']
X = df.drop(columns=['Class'], axis=1)

Transformarea caracteristicilor categoriale în caracteristici numerice

Referitor la noastre Class coloană – valorile sale nu sunt numere, asta înseamnă că trebuie să le transformăm. Există multe moduri de a face această transformare; aici, vom folosi replace() metoda și înlocuiți Çerçevelik la 0 și Ürgüp Sivrisi la 1.

y = y.replace('Çerçevelik', 0).replace('Ürgüp Sivrisi', 1)

Tine cont de cartografiere! Când citiți rezultatele din modelul dvs., veți dori să le convertiți înapoi cel puțin în minte sau înapoi în numele clasei pentru alți utilizatori.

Împărțirea datelor în seturi de tren și de testare

În explorarea noastră, am observat că funcțiile au nevoie de scalare. Dacă am face scalarea acum, sau într-un mod automat, am scala valorile cu întregul X și y. În acest caz, ne-am prezenta scurgeri de date, deoarece valorile setului de testare care urmează să fie în curând ar fi afectat scalarea. Scurgerea de date este o cauză comună a rezultatelor ireproductibile și a performanțelor ridicate iluzorii ale modelelor ML.

Gândindu-ne la scalare, arată că mai întâi trebuie să ne despărțim X și y date mai departe în tren și seturi de testare și apoi la potrivi un scaler pe setul de antrenament și să transforma atât trenul, cât și seturile de testare (fără ca setul de testare să afecteze vreodată scalatorul care face acest lucru). Pentru aceasta, vom folosi Scikit-Learn's train_test_split() metodă:

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)

reglaj test_size=.25 se asigură că folosim 25% din date pentru testare și 75% pentru instruire. Acest lucru ar putea fi omis, odată ce este împărțirea implicită, dar Pitonic Modul de scriere a codului sugerează că a fi „explicit este mai bine decât implicit”.

Notă: Propoziția „explicit este mai bine decât implicit” este o referire la Zenul lui Python, sau PEP20. Prezintă câteva sugestii pentru scrierea codului Python. Dacă aceste sugestii sunt urmate, codul este luat în considerare Pitonic. Puteți afla mai multe despre asta aici.

După împărțirea datelor în seturi de tren și de testare, este o practică bună să vă uitați la câte înregistrări sunt în fiecare set. Asta se poate face cu shape atribut:

X_train.shape, X_test.shape, y_train.shape, y_test.shape

Aceasta afișează:

((1875, 12), (625, 12), (1875,), (625,))

Putem vedea că după despărțire avem 1875 de înregistrări pentru antrenament și 625 pentru testare.

Scalare date

Odată ce avem trenul și seturile de testare pregătite, putem trece la scalarea datelor cu Scikit-Learn StandardScaler obiect (sau alte scaler furnizate de bibliotecă). Pentru a evita scurgerile, detartratorul este montat pe X_train datele și valorile trenului sunt apoi utilizate pentru a scala – sau transforma – atât datele trenului, cât și cele de testare:

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

Deoarece veți suna de obicei:

scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

Primele două rânduri pot fi restrânse cu un singular fit_transform() apel, care se potrivește cu scaler-ul de pe platou și îl transformă dintr-o singură mișcare. Acum putem reproduce graficele boxplot pentru a vedea diferența după scalarea datelor.

Având în vedere că scalarea elimină numele coloanelor, înainte de trasare, putem organiza din nou datele trenului într-un cadru de date cu nume de coloane pentru a facilita vizualizarea:

column_names = df.columns[:12] 
X_train = pd.DataFrame(X_train, columns=column_names)

sns.boxplot(data=X_train, orient='h')

Ghid definitiv pentru regresia logistică în Python PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

Putem vedea în sfârșit toate boxploturile noastre! Observați că toate au valori aberante și caracteristicile care prezintă o distribuție mai departe de normal (care au curbe înclinate fie spre stânga, fie spre dreapta), cum ar fi Solidity, Extent, Aspect_Ration, și Compactedness, sunt aceleași care au avut corelații mai mari.

Eliminarea valorii aberante cu metoda IQR

Știm deja că regresia logistică poate fi afectată de valori aberante. Una dintre modalitățile de a le trata este utilizarea unei metode numite Intervalul intercuartil or I.Q.R.. Pasul inițial al metodei IQR este împărțirea datelor noastre de tren în patru părți, numite quartile. Prima quartila, Q1, reprezintă 25% din date, al doilea, Q2, la 50%, al treilea, Q3, la 75%, iar ultimul, Q4, la 100%. Casetele din boxplot sunt definite prin metoda IQR și sunt o reprezentare vizuală a acesteia.

Luând în considerare un boxplot orizontal, linia verticală din stânga marchează 25% din date, linia verticală din mijloc, 50% din date (sau mediana), iar ultima linie verticală din dreapta, 75% din date . Cu cât ambele pătrate definite de liniile verticale sunt mai egale în dimensiune – sau cu cât linia verticală mediană este mai mare în mijloc – înseamnă că datele noastre sunt mai aproape de distribuția normală sau mai puțin denaturate, ceea ce este util pentru analiza noastră.

Pe lângă caseta IQR, există și linii orizontale pe ambele părți ale acesteia. Aceste linii marchează valorile de distribuție minime și maxime definite de

$$
Minim = Q1 – 1.5*IQR
$$

și

$$
Maxim = Q3 + 1.5*IQR
$$

IQR este exact diferența dintre Q3 și Q1 (sau Q3 – Q1) și este cel mai central punct al datelor. De aceea, atunci când găsim IQR, ajungem să filtram valorile aberante din extremitățile datelor, sau în punctele minime și maxime. Box plots ne oferă o perspectivă a ceea ce va fi rezultatul metodei IQR.

Ghid definitiv pentru regresia logistică în Python PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

Putem folosi Pandas quantile() metoda de a găsi cuantilele noastre și iqr de la scipy.stats pachet pentru a obține intervalul de date interquartile pentru fiecare coloană:

from scipy.stats import iqr

Q1 = X_train.quantile(q=.25)
Q3 = X_train.quantile(q=.75)

IQR = X_train.apply(iqr)

Acum avem Q1, Q3 și IQR, putem filtra valorile mai aproape de mediană:


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]

După ce ne-am filtrat rândurile de antrenament, putem vedea câte dintre ele sunt încă în date cu shape:

X_train.shape

Rezultă:

(1714, 12)

Putem vedea că numărul de rânduri a trecut de la 1875 la 1714 după filtrare. Aceasta înseamnă că 161 de rânduri au conținut valori aberante sau 8.5% din date.

Notă: Se recomandă ca filtrarea valorilor aberante, eliminarea valorilor NaN și alte acțiuni care implică filtrarea și curățarea datelor să rămână sub sau până la 10% din date. Încercați să vă gândiți la alte soluții dacă filtrarea sau eliminarea dvs. depășește 10% din datele dvs.

După eliminarea valorii aberante, suntem aproape gata să includem date în model. Pentru montarea modelului, vom folosi datele trenului. X_train este filtrat, dar ce zici y_train?

y_train.shape

Acest rezultat:

(1875,)

Observa asta y_train mai are 1875 de rânduri. Trebuie să potrivim numărul de y_train rânduri la numărul de X_train rânduri și nu doar în mod arbitrar. Trebuie să eliminăm valorile y ale cazurilor de semințe de dovleac pe care le-am îndepărtat, care sunt probabil împrăștiate prin y_train a stabilit. Cel filtrat X_train stil are indicii sai originali, iar indicele are lacune de unde am eliminat valorile aberante! Apoi putem folosi indexul lui X_train DataFrame pentru a căuta valorile corespunzătoare în y_train:

y_train = y_train.iloc[X_train.index]

După ce facem asta, ne putem uita la y_train forma din nou:

y_train.shape

Care iese:

(1714,)

Consultați ghidul nostru practic și practic pentru a învăța Git, cu cele mai bune practici, standarde acceptate de industrie și fisa de cheat incluse. Opriți căutarea pe Google a comenzilor Git și de fapt învăţa aceasta!

Acum, y_train are, de asemenea, 1714 rânduri și sunt la fel ca și X_train rânduri. Suntem în sfârșit gata să creăm modelul nostru de regresie logistică!

Implementarea modelului de regresie logistică

Partea grea este gata! Preprocesarea este de obicei mai dificilă decât dezvoltarea modelului, atunci când vine vorba de utilizarea bibliotecilor precum Scikit-Learn, care au simplificat aplicarea modelelor ML la doar câteva linii.

În primul rând, importăm LogisticRegression clasă și instanțiază-o, creând un LogisticRegression obiect:

from sklearn.linear_model import LogisticRegression
logreg = LogisticRegression(random_state=SEED)

În al doilea rând, ne potrivim datele trenului la logreg model cu fit() metoda și preziceți datele noastre de testare cu predict() metoda, stocând rezultatele ca y_pred:



logreg.fit(X_train.values, y_train)
y_pred = logreg.predict(X_test)

Am făcut deja predicții cu modelul nostru! Să ne uităm la primele 3 rânduri din X_train pentru a vedea ce date am folosit:

X_train[:3]

Codul de mai sus iese:

       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

Și la primele 3 predicții în y_pred pentru a vedea rezultatele:

y_pred[:3] 

Rezultă:

array([0, 0, 0])

Pentru acele trei rânduri, predicțiile noastre au fost că erau semințe de prima clasă, Çerçevelik.

cu regresie logistică, în loc să prezică clasa finală, cum ar fi 0, putem de asemenea prezice probabilitatea pe care o are rândul să aparțină la 0 clasă. Acesta este ceea ce se întâmplă de fapt atunci când regresia logistică clasifică datele și predict() metoda trece apoi această predicție printr-un prag pentru a returna o clasă „hard”. Pentru a prezice probabilitatea de a face parte dintr-o clasă, predict_proba() este folosit:

y_pred_proba = logreg.predict_proba(X_test)

Să aruncăm o privire și asupra primelor 3 valori ale predicțiilor probabilităților y:

y_pred_proba[:3] 

Care iese:

        # class 0   class 1   
array([[0.54726628, 0.45273372],
       [0.56324527, 0.43675473],
       [0.86233349, 0.13766651]])

Acum, în loc de trei zerouri, avem o coloană pentru fiecare clasă. În coloana din stânga, începând cu 0.54726628, sunt probabilitățile datelor care aparțin clasei 0; iar în coloana din dreapta, începând cu 0.45273372, sunt probabilitatea ca aceasta să aparțină clasei 1.

Notă: Această diferență de clasificare este cunoscută și ca greu și moale predictie. Predicțiile hard încadrează predicția într-o clasă, în timp ce predicțiile soft generează probabilitate a instanţei aparţinând unei clase.

Există mai multe informații despre modul în care a fost realizată rezultatul estimat. Nu a fost de fapt 0, dar o șansă de 55% la curs 0, și o șansă de 45% la curs 1. Aceasta arată cum primele trei X_test puncte de date, referitoare la clasă 0, sunt chiar clare doar în ceea ce privește al treilea punct de date, cu o probabilitate de 86% – și nu atât pentru primele două puncte de date.

Când comunicați constatări folosind metode ML – de obicei este mai bine să returnați o clasă soft și probabilitatea asociată ca "încredere" din acea clasificare.

Vom vorbi mai multe despre modul în care se calculează atunci când vom aprofunda modelul. În acest moment, putem trece la pasul următor.

Evaluarea modelului cu rapoarte de clasificare

Al treilea pas este să vedem cum funcționează modelul pe datele de testare. Putem importa Scikit-Learn classification_report() și treci de la noi y_test și y_pred ca argumente. După aceea, putem tipări răspunsul acestuia.

Raportul de clasificare conține cele mai utilizate valori de clasificare, cum ar fi precizie, rechemare, scor f1, și precizie.

  1. Precizie: pentru a înțelege ce valori corecte de predicție au fost considerate corecte de către clasificatorul nostru. Precizia va împărți acele valori pozitive adevărate la orice a fost prezis ca fiind pozitiv:

$$
precizie = frac{text{adevărat pozitiv}}{text{adevărat pozitiv} + text{fals pozitiv}}
$$

  1. Rechemare: pentru a înțelege câte dintre adevăratele pozitive au fost identificate de clasificatorul nostru. Rechemarea se calculează împărțind adevăratele pozitive la orice ar fi trebuit prezis ca pozitiv:

$$
recall = frac{text{adevărat pozitiv}}{text{adevărat pozitiv} + text{fals negativ}}
$$

  1. Scor F1: este echilibrat sau medie armonică de precizie și reamintire. Cea mai mică valoare este 0, iar cea mai mare este 1. Când f1-score este egal cu 1, înseamnă că toate clasele au fost prezise corect – acesta este un scor foarte greu de obținut cu date reale:

$$
text{f1-score} = 2* frac{text{precizie} * text{recall}}{text{precizie} + text{recall}}
$$

  1. Acuratete: descrie câte predicții a corectat clasificatorul nostru. Cea mai mică valoare de precizie este 0, iar cea mai mare este 1. Această valoare este de obicei înmulțită cu 100 pentru a obține un procent:

$$
acuratețe = frac{text{numărul de predicții corecte}}{text{numărul total de predicții}}
$$

Notă: Este extrem de greu să obțineți acuratețe de 100% pentru orice date reale, dacă se întâmplă acest lucru, fiți conștienți de faptul că s-ar putea întâmpla o scurgere sau ceva greșit - nu există un consens cu privire la o valoare ideală a preciziei și este, de asemenea, dependentă de context. O valoare de 70%, ceea ce înseamnă că clasificatorul va face greșeli în 30% din date sau peste 70% tinde să fie suficientă pentru majoritatea modelelor.

from sklearn.metrics import classification_report
cr = classification_report(y_test, y_pred)
print(cr)

Apoi putem analiza rezultatul raportului de clasificare:

				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

Acesta este rezultatul nostru. Observa asta precision, recall, f1-score, și accuracy toate valorile sunt foarte mari, peste 80%, ceea ce este ideal – dar acele rezultate au fost probabil influențate de corelații mari și nu se vor menține pe termen lung.

Precizia modelului este de 86%, ceea ce înseamnă că greșit în 14% din cazuri. Avem acele informații generale, dar ar fi interesant de știut dacă cele 14% greșeli se întâmplă în ceea ce privește clasificarea clasei 0 sau clasa 1. Pentru a identifica clasele care sunt identificate greșit și în ce frecvență – putem calcula și reprezenta un grafic a matrice de confuzie a predicțiilor modelului nostru.

Evaluarea modelului cu o matrice de confuzie

Să calculăm și apoi să trasăm matricea de confuzie. După ce facem asta, putem înțelege fiecare parte a acesteia. Pentru a reprezenta matricea de confuzie, vom folosi Scikit-Learn confusion_matrix(), pe care îl vom importa din metrics modul.

Matricea de confuzie este mai ușor de vizualizat folosind un Seaborn heatmap(). Deci, după generarea acesteia, vom trece matricea noastră de confuzie ca argument pentru harta termică:

from sklearn.metrics import confusion_matrix

cm = confusion_matrix(y_test, y_pred)
sns.heatmap(cm, annot=True, fmt='d')

Ghid definitiv pentru regresia logistică în Python PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

  1. Matricea confuziei: matricea arată câte mostre modelul a fost corect sau greșit pentru fiecare clasă. Se numesc valorile care au fost corecte și prezise corect adevărate pozitive, iar cele care au fost prezise ca pozitive, dar nu au fost pozitive sunt numite fals pozitive. Aceeași nomenclatură a negative adevărate și false negative este folosit pentru valori negative;

Privind graficul matricei de confuzie, putem vedea că avem 287 valori care au fost 0 si prezis ca 0 - sau adevărate pozitive pentru clasă 0 (semințele de Çerçevelik). De asemenea avem 250 adevărate pozitive pentru clasă 1 (Semințe de Ürgüp Sivrisi). Adevărații pozitive sunt întotdeauna localizate în diagonala matricei care merge din stânga sus la dreapta jos.

De asemenea avem 29 valori care trebuiau să fie 0, dar prezis ca 1 (fals pozitive) Şi 59 valori care au fost 1 si prezis ca 0 (false negative). Cu aceste numere, putem înțelege că eroarea pe care modelul o face cel mai mult este că prezice negative false. Deci, în mare parte poate ajunge să clasifice o sămânță de Ürgüp Sivrisi drept sămânță de Çerçevelik.

Acest tip de eroare se explică și prin rechemarea de 81% a clasei 1. Observați că valorile sunt conectate. Iar diferența în rechemare vine din faptul că avem cu 100 de mostre mai puține din clasa Ürgüp Sivrisi. Aceasta este una dintre implicațiile de a avea doar câteva mostre mai puțin decât cealaltă clasă. Pentru a îmbunătăți și mai mult reamintirea, puteți fie să experimentați cu greutăți de clasă, fie să utilizați mai multe mostre Ürgüp Sivrisi.

Până acum, am executat majoritatea pașilor tradiționali ai științei datelor și am folosit modelul de regresie logistică ca o cutie neagră.

Notă: Dacă vrei să mergi mai departe, folosește Validare încrucișată (CV) și căutare în grilă să caute, respectiv, modelul care generalizează cel mai mult în ceea ce privește datele și cei mai buni parametri de model care sunt aleși înainte de antrenament, sau hiperparametri.

În mod ideal, cu CV și Grid Search, ați putea implementa, de asemenea, o modalitate concatenată de a face pașii de preprocesare a datelor, împărțirea datelor, modelare și evaluare - ceea ce este simplificat cu Scikit-Learn conducte.

Acum este momentul să deschidem cutia neagră și să privim în interiorul ei, pentru a înțelege mai profund cum funcționează regresia logistică.

Aprofundarea cum funcționează cu adevărat regresia logistică

regres Cuvântul nu este acolo din întâmplare, pentru a înțelege ce face regresia logistică, ne putem aminti ce face regresia liniară fratelui său cu datele. Formula de regresie liniară a fost următoarea:

$$
y = b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n
$$

În care b0 a fost interceptarea regresiei, b1 coeficientul și x1 datele.

Acea ecuație a rezultat într-o linie dreaptă care a fost folosită pentru a prezice noi valori. Reamintind introducerea, diferența acum este că nu vom prezice valori noi, ci o clasă. Deci linia dreaptă trebuie să se schimbe. Cu regresia logistică, introducem o neliniaritate și predicția se face acum folosind o curbă în loc de o linie:

Ghid definitiv pentru regresia logistică în Python PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

Observați că, în timp ce linia de regresie liniară continuă și este formată din valori infinite continue, curba de regresie logistică poate fi împărțită la mijloc și are extreme în valori 0 și 1. Forma „S” este motivul pentru care clasifică datele – punctele care sunt mai aproape sau cad pe extremitatea cea mai înaltă aparțin clasei 1, în timp ce punctele care se află în cadranul inferior sau mai aproape de 0 aparțin clasei 0. „S” este mijlocul între 0 și 1, 0.5 – este pragul pentru punctele de regresie logistică.

Ghid definitiv pentru regresia logistică în Python PlatoBlockchain Data Intelligence. Căutare verticală. Ai.

Înțelegem deja diferența vizuală dintre regresia logistică și regresia liniară, dar cum rămâne cu formula? Formula de regresie logistică este următoarea:

$$
y = b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n
$$

Se mai poate scrie ca:

$$
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)}}
$$

Sau chiar să fie scris ca:

$$
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 + ldots + b_n * x_n)}}
$$

În ecuația de mai sus, avem probabilitatea de intrare, în loc de valoarea acesteia. Are 1 ca numărător, astfel încât poate rezulta o valoare între 0 și 1 și 1 plus o valoare la numitorul său, astfel încât valoarea sa este 1 și ceva - asta înseamnă că rezultatul întregii fracții nu poate fi mai mare de 1 .

Și care este valoarea care este în numitor? Este e, baza logaritmului natural (aproximativ 2.718282), ridicată la puterea regresiei liniare:

$$
e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$

Un alt mod de a scrie ar fi:

$$
ln stânga( frac{p}{1-p} dreapta) = {(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$

În acea ultimă ecuație, ln este logaritmul natural (baza e) și p este probabilitatea, deci logaritmul probabilității rezultatului este același cu rezultatul regresiei liniare.

Cu alte cuvinte, cu rezultatul regresiei liniare și logaritmul natural, putem ajunge la probabilitatea unei intrări aparținând sau nu unei clase proiectate.

Întregul proces de derivare a regresiei logistice este următorul:

$$
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 + ldots + 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)}
$$

$$
ln stânga( frac{p}{1-p} dreapta) = (b_0 + b_1 * x_1 + b_2 *x_2 + b_3 * x_3 + ldots + b_n * x_n)
$$

Aceasta înseamnă că modelul de regresie logistică are și coeficienți și o valoare de interceptare. Deoarece folosește o regresie liniară și îi adaugă o componentă neliniară cu logaritmul natural (e).

Putem vedea valorile coeficienților și interceptarea modelului nostru, la fel ca și pentru regresia liniară, folosind coef_ și intercept_ proprietăţi:

logreg.coef_

Care afișează coeficienții fiecăreia dintre cele 12 caracteristici:

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_

Asta are ca rezultat:

array([0.08735782])

Cu coeficienții și valorile de interceptare, putem calcula probabilitățile prezise ale datelor noastre. Să luăm primul X_test valorile din nou, de exemplu:

X_test[:1]

Aceasta returnează primul rând de X_test ca o matrice 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]])

Urmând ecuația inițială:

$$
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 + ldots + b_n * x_n)}}
$$

În python, avem:

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

Rezultă:

0.45273372469369133

Dacă ne uităm din nou la predict_proba rezultatul primei X_test linie, avem:

logreg.predict_proba(X_test[:1])


Aceasta înseamnă că ecuația originală de regresie logistică ne oferă probabilitatea intrării în ceea ce privește clasa 1, pentru a afla ce probabilitate este pentru clasă 0, putem pur și simplu:

1 - px


Observați că ambele px și 1-px sunt identice cu predict_proba rezultate. Acesta este modul în care se calculează regresia logistică și de ce regres face parte din numele său. Dar cum rămâne cu termenul logistic?

Termenul logistic vine de la logit, care este o funcție pe care am văzut-o deja:

$$
în stânga (frac{p}{1-p} dreapta)
$$

Tocmai am calculat-o cu px și 1-px. Acesta este logit-ul, numit și log-cote deoarece este egal cu logaritmul cotelor unde p este o probabilitate.

Concluzie

În acest ghid, am studiat unul dintre cei mai fundamentali algoritmi de clasificare a învățării automate, adică regresie logistică.

Inițial, am implementat regresia logistică ca o cutie neagră cu biblioteca de învățare automată a lui Scikit-Learn, iar ulterior am înțeles-o pas cu pas pentru a avea clar de ce și de unde provin termenii regresie și logistică.

De asemenea, am explorat și studiat datele, înțelegând că aceasta este una dintre cele mai importante părți ale unei analize a științei datelor.

De aici, te-aș sfătui să te joci regresie logistică multiclasă, regresie logistică pentru mai mult de două clase – puteți aplica același algoritm de regresie logistică pentru alte seturi de date care au mai multe clase și puteți interpreta rezultatele.

Notă: Este disponibilă o colecție bună de seturi de date aici cu care să te joci.

De asemenea, te-aș sfătui să studiezi L1 și L2 regularizări, sunt o modalitate de a „penaliza” datele superioare pentru ca acestea să devină mai aproape de normal, menținând complexitatea modelului, astfel încât algoritmul să poată ajunge la un rezultat mai bun. Implementarea Scikit-Learn pe care am folosit-o, are deja regularizare L2 în mod implicit. Un alt lucru de privit este diferit rezolvatori, Cum ar fi lbgs, care optimizează performanța algoritmului de regresie logistică.

De asemenea, este important să aruncați o privire asupra statistic abordarea regresiei logistice. Are ipoteze despre comportamentul datelor și despre alte statistici care trebuie să fie valabile pentru a garanta rezultate satisfăcătoare, cum ar fi:

  • observațiile sunt independente;
  • nu există multicoliniaritate între variabilele explicative;
  • nu există valori aberante extreme;
  • există o relație liniară între variabilele explicative și logit-ul variabilei răspuns;
  • dimensiunea eșantionului este suficient de mare.

Observați câte dintre aceste ipoteze au fost deja acoperite în analiza și tratarea datelor noastre.

Sper că veți continua să explorați ce are de oferit regresia logistică în toate abordările sale diferite!

Timestamp-ul:

Mai mult de la Stackabuse