Documente Academic
Documente Profesional
Documente Cultură
In [1]: ?range
python într-un mod mai prietenos: (inclusive) to stop (exclusive) by step. range(i, j) produces i,
i+1, i+2, ..., j-1. start defaults to 0, and stop is omitted!
range(4) produces 0, 1, 2, 3. These are exactly the valid indices
– Sunt disponibile multe funcții utilitare (ex. ls, In [2]: print(*range(1, 7, 2))
1 3 5
pwd, cd)
– Acces la funcții magice (ex. %run, %timeit, Comanda range creează o
%edit, %paste, %pastebin) listă de întregi. Se poate
compara cu sintaxa Matlab
1:2:6
Ajutor
• Pentru fiecare comandă, aveți acces la ajutor pentru a vă reîmprospăta
memoria:
python
>>> help("".strip)
Help on built-in function strip:
și scipy
• NumPy oferă un tablou numeric ca și
>>> # Am dori sa numim numpy mai scurt np
>>> import numpy as np
alternativă la lista Python >>>
>>> # Definim un tablou numpy (vector):
• Tipul listă este prea generic și acceptă >>> v = np.array([1, 2, 3, 4])
>>>
orice mix de tipuri de date >>> # Obs: instructiunea de mai sus face cast
>>> # a unei liste Python la un tablou numpy
• Deși practic pentru manipulări generice, >>>
>>> # Redimensionare la o matrice 2x2
devine ineficient în calcule >>> V = np.resize(v, (2, 2))
• Cele mai multe funcții pe vector/matrice sunt similare celor din Matlab:
>>> np.linspace(1, 10, 5) # Argumente: (start, end, num_items)
array([ 1. , 3.25, 5.5 , 7.75, 10. ])
>>>
>>> np.eye(3)
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
>>>
>>> np.random.randn(2, 3)
array([[-0.06274209, -1.58088495, -0.32318544],
[-0.58858417, 0.79139608, -0.17651722]])
Matrici
• O matrice este definită similar, fie specificând valorile manual sau folosind
funcții speciale
>>> # O matrice este pur si simplu un tablou de tablouri
>>> # Poate parea complicat la inceput, dar este defapt
>>> # chiar elegant pentru tablouri N-dimensionale
>>>
>>> np.array([[1, 2], [3, 4]])
array([[1, 2],
[3, 4]])
>>>
>>> from scipy.linalg import toeplitz, hilbert # S-ar putea si "...import *"
>>> toeplitz([3, 1, -2])
array([[ 3, 1, -2],
[ 1, 3, 1],
[-2, 1, 3]])
>>>
>>> hilbert(3)
array([[1. , 0.5 , 0.33333333],
[0.5 , 0.33333333, 0.25 ],
[0.33333333, 0.25 , 0.2 ]])
Produsul matricelor
• Înmulțirea matricelor
este diferită față de >>> A = np.array([[1, 2], [3, 4]])
>>> B = np.array([[5, 6], [7, 8]])
>>>
Matlab. >>> A * B # Inmultire element cu element (Matlab: A .* B)
array([[ 5, 12],
[21, 32]])
Indici pozitivi 0 1 2 3 4 5 6 7 8 9
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
Tablou 1 2 3 4 5 6 7 8 9 10
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
Indici negativi -10 -9 -8 -7 -6 -5 -4 -3 -2 -1
Indexarea
• Deasemenea tablourile N-dimensionale >>> M = np.reshape(np.arange(0, 36), (6, 6))
(matrici) pot fi indexați în mod similar. >>> M
array([[ 0, 1, 2, 3, 4, 5],
Această operațiune se numește slicing și [ 6, 7, 8, 9, 10, 11],
rezultatul este un slice al matricii. [12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23],
• În exemplul dat, extragem elementele de [24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35]])
pe rândurile 2:4 = [2,3] și coloanele 1, 2, 4 >>> M[2:4, [1,2,4]]
(cele cu roșu) array([[13, 14, 16],
[19, 20, 22]])
• De notat că primul index este cel de rând,
NU ”coordonata x”
• Această ordine este numită ”stil Fortran”
sau ”column major”, alternativa fiind ”stil
C” sau ”row major”
Indexarea
• Pentru a specifica doar indici pentru >>> M = np.reshape(np.arange(0, 36), (6, 6))
colane sau rânduri, se folosește ”:” >>> M
array([[ 0, 1, 2, 3, 4, 5],
singur [ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
• Exemplul extrage ultimele două [18, 19, 20, 21, 22, 23],
[24, 25, 26, 27, 28, 29],
• numpy.genfromtxt "2",1613.63,1688.5,1750.5,2460.2
"3",1606.51,1678.6,1718,2448.2
• csv.reader "4",1621.04,1684.1,1708.1,2470.4
"5",1618.16,1686.6,1723.1,2484.7
• pandas.read_csv "6",1610.61,1671.6,1714.3,2466.8
"7",1630.75,1682.9,1734.5,2487.9
"8",1640.17,1703.6,1757.4,2508.4
"9",1635.47,1697.5,1754,2510.5
"10",1645.89,1716.3,1754.3,2497.4
Exemplu – citirea de date
• https://raw.githubusercontent.com/vincentarelbundock/Rdatasets/master/csv/datasets/EuStockMarkets.csv
plt.grid(True)
plt.xlabel("Timpul in $\mu$S")
plt.ylabel("Amplitudinea")
plt.title("Un grafic exemplu")
plt.legend(loc = "upper left")
• Concluzie:
– Lungimea este o caracteristică slabă luată separat!
• Pasul următor:
– Selectăm strălucirea ca și o posibilă caracteristică.
Un exemplu
• Avem o îmbunătățire
Un exemplu
• Am putea adăuga și alte caracteristici care nu sunt
corelate cu cele pe care le avem deja.
– O precauție trebuie totuși luată ca să nu reducem
performanțele prin adăugarea unor ”caracteristici
zgomotoase”
• Ideal, cea mai bună graniță de decizie ar trebui să fie cea
care oferă o performanță optimă ca cea din următoarea
figură
Un exemplu
• O separare perfectă!
• Dar ce specie e ?
Un exemplu
• Cu toate acestea, satisfacția noastră e prematură
deoarece ținta principală în proiectarea unui
clasificator este acela de a clasifica în mod corect
intrări noi!
• Problemă de generalizare!
Un exemplu
• Colectarea datelor
• Alegerea caracteristicilor
• Alegerea modelului
• Antrenarea
• Evaluarea
• Complexitatea computațională
Ciclul de proiectare
• Colectarea datelor
– Cum putem să știm dacă
am cules un set adecvat și
reprezentativ de exemple
pentru antrenarea și
testarea sistemului?
Ciclul de proiectare
• Alegerea caracteristicilor
– Depinde de caracteristicile
domeniului problemei
– Simplu de extras, invariant
la transformări irelevante,
insensibil la zgomot
Ciclul de proiectare
• Alegerea modelului
– Nesatisfăcuți cu
performanțele sistemului
nostru de clasificare ar
trebui să testăm și alte clase
de modele
Ciclul de proiectare
• Antrenarea
– Folosirea de date pentru a
determina clasificatorul
– Există multe proceduri
diferite pentru antrenarea
clasificatorilor și pentru
alegerea modelelor
Ciclul de proiectare
• Evaluarea
– Măsurarea ratei de eroare
(sau performanței) și
trecerea de la un set de
caracteristici la un alt set
Ciclul de proiectare
• Complexitatea computațională
– Care este punctul de echilibru
între ușurința computațională
și performanță?
– Cum se scalează un algoritm
ca o funcție de numărul de
caracteristici, tipare sau
categorii?
Învățarea și Adaptarea
• Învățarea supervizată
– Un specialist din domeniu asigură o etichetă de
categorie sau cost pentru fiecare tipar din setul de
antrenare
• Învățarea nesupervizată
– Sistemul formează clustere de ”grupări naturale”
din tiparele de intrare
Prelucrarea datelor
• Încărcarea datelor
• Curățarea și manipularea datelor
• Inspectarea datelor
• Prezentarea rezultatelor ca și:
– Valori
– Foi de lucru
– Grafice
– Altele
Ce vom face?
• Vom simula datele pentru o anumită campanie de publicitate
• Creăm date, simulând faptul că pot veni într-un format care
nu este perfect sau pregătit pentru prelucrare
• Le curățăm și le încărcăm în unealta principală pe care o vom
folosi, cum ar fi DataFrame din librăria pandas
• Manipulăm datele din DataFrame
• Salvăm datele din DataFrame într-un fișier în diverse formate
• Inspectăm datele și obținem niște rezultate din ele
Pregătire notebook
#1
import json
import random
from datetime import date, timedelta
import faker
Pregătirea datelor
• Structura de date:
– O listă de obiecte utilizator
– Fiecare obiect utilizator va fi legat de un număr de obiecte de campanie
• Instanțiem clasa Faker pe care o să îl utilizăm la generarea de date
#2
fake = faker.Faker()
• Generăm 1000 de nume de utilizatori
#3
usernames = set()
usernames_no = 1000
def get_users(usernames):
users = []
for username in usernames:
name, gender = get_random_name_and_gender()
user = {
'username': username,
'name': name,
'gender': gender,
'email': fake.email(),
'age': fake.random_int(min=18, max=90),
'address': fake.address(),
}
users.append(json.dumps(user))
return users
users = get_users(usernames)
users[:3]
Pregătirea datelor
• Generarea unei #5
# campaign name format:
# InternalType_StartDate_EndDate_TargetAge_TargetGender_Currency
def get_type():
# just some gibberish internal codes
def get_start_end_dates():
duration = random.randint(1, 2 * 365)
offset = random.randint(-365, 365)
start = date.today() - timedelta(days=offset)
end = start + timedelta(days=duration)
def _format_date(date_):
return date_.strftime("%Y%m%d")
return _format_date(start), _format_date(end)
def get_age():
age = random.randint(20, 45)
age -= age % 5
diff = random.randint(5, 25)
diff -= diff % 5
return '{}-{}'.format(age, age + diff)
def get_gender():
return random.choice(('M', 'F', 'B'))
def get_currency():
return random.choice(('GBP', 'EUR', 'USD'))
def get_campaign_name():
separator = '_'
type_ = get_type()
start, end = get_start_end_dates()
age = get_age()
gender = get_gender()
currency = get_currency()
return separator.join((type_, start, end, age, gender, currency))
Pregătirea datelor
• Asamblarea datelor
#7
def get_data(users):
data = []
for user in users:
campaigns = [get_campaign_data()
for _ in range(random.randint(2, 8))]
data.append({'user': user, 'campaigns': campaigns})
return data
Curățarea datelor
• Să aruncăm o privire
#8
rough_data = get_data(users)
rough_data[:2] # let's take a peek
• Salvăm datele
#10
with open('data.json', 'w') as stream:
stream.write(json.dumps(data))
Crearea DataFrame
• Inițializăm un nou Notebook
#1
import json
import calendar
import numpy as np
from pandas import DataFrame
import arrow
import pandas as pd
• Încărcăm datele
#2
with open('data.json') as stream:
data = json.loads(stream.read())
• Creăm un DataFrame
#3
df = DataFrame(data)
df.head()
Analiza datelor
• O vedere de ansamblu asupra datelor
#4
df.count()
#7
df.sort_values(by=['cmp_bgt'], ascending=False).tail(3)
Decodificarea numelui de campanie
• Vom folosi metoda apply a obiectului Series
#8
def unpack_campaign_name(name):
# very optimistic method, assumes data in campaign name
# is always in good state
type_, start, end, age, gender, currency = name.split('_')
start = arrow.get(start, 'YYYYMMDD').date()
end = arrow.get(end, 'YYYYMMDD').date()
return type_, start, end, age, gender, currency
campaign_data = df['cmp_name'].apply(unpack_campaign_name)
campaign_cols = ['Type', 'Start', 'End', 'Age', 'Gender', 'Currency']
campaign_df = DataFrame(
campaign_data.tolist(), columns=campaign_cols, index=df.index)
campaign_df.head(3)
#10
df[['cmp_name'] + campaign_cols].head(3)
Despachetarea datelor utilizator
• Vom folosi aceeași strategie – unpack, join, peek
#11
def unpack_user_json(user):
# very optimistic as well, expects user objects
# to have all attributes
user = json.loads(user.strip())
return [
user['username'],
user['email'],
user['name'],
user['gender'],
user['age'],
user['address'],
]
user_data = df['user'].apply(unpack_user_json)
user_cols = ['username', 'email', 'name', 'gender', 'age', 'address']
user_df = DataFrame(user_data.tolist(), columns=user_cols, index=df.index)
#12
df = df.join(user_df)
#13
df[['user'] + user_cols].head(2)
Redenumim câteva coloane
• Am putea folosi denumiri mai potrivite pentru câteva coloane
#14
better_columns = [
'cmp_name', 'Budget', 'Spent’,
'Clicks', 'Impressions’, 'user',
'Type', 'Start', 'End',
'Target Age', 'Target Gender', 'Currency',
'Username', 'Email', 'Name',
'Gender', 'Age', 'Address',
]
df.columns = better_columns
Adăugăm coloane suplimentare - măsuri
• Pentru fiecare campanie avem:
– Numărul de click-uri
– Numărul de afișări
– Suma cheltuită
• Măsuri noi: #15
– CTR – Click Through Rate def calculate_extra_columns(df):
# Click Through Rate
– CPC – Cost Per Click df['CTR'] = df['Clicks'] / df['Impressions']
# Cost Per Click
calculate_extra_columns(df)
• Să aruncăm o privire
#16
df[['Spent', 'Clicks', 'Impressions',
'CTR', 'CPC', 'CPI']].head(3)
Verificăm acuratețea pentru câteva cazuri
def get_duration(row):
return (row['End'] - row['Start']).days
• Verificăm rezultatele
#19
df[['Start', 'End', 'Duration', 'Day of Week']].head(3)
Curățare
• Putem deasemenea șterge câteva coloane de care nu avem nevoie
– cmp_name
– user
• Putem deasemenea reordona coloanele dintr-un DataFrame pentru a fi
mai relevante
#20
final_columns = [
'Type', 'Start', 'End', 'Duration', 'Day of Week', 'Budget',
'Currency', 'Clicks', 'Impressions', 'Spent', 'CTR', 'CPC',
'CPI', 'Target Age', 'Target Gender', 'Username', 'Email',
'Name', 'Gender', 'Age'
]
df = df[final_columns]
Salvarea DataFrame într-un fișier
• În CSV
#21
df.to_csv('df.csv')
• În JSON
#22
df.to_json('df.json')
• În Excel
#23
df.to_excel('df.xlsx')
#32
pivot = df.pivot_table(
values=['Impressions', 'Clicks', 'Spent'],
index=['Target Age'],
columns=['Target Gender'],
aggfunc=np.sum
)
pivot
Întrebări?
Sisteme de Recunoaștere a Formelor
(Machine Learning & Data Mining)
Curs 02 – Teoria Estimării
prof. dr. ing. Robert Győrödi
Sisteme de Recunoaștere a Formelor
• Fiecare pereche de a și b
reprezintă o linie
• Care linie din cele trei ar descrie
cel mai bine setul de date?
• Sau oare altă linie ar fi mai
potrivită?
Exemplu: o linie dreaptă
• Poate fi arătat că cea mai bună soluție (în sensul celei mai bune
similitudini – definit mai târziu) este dată de:
𝑁−1 𝑁−1
6 12
𝑎ො = − 𝑦 𝑛 + 𝑥 𝑛 𝑦 𝑛
𝑁 𝑁+1 𝑁 𝑁2 − 1
𝑛=0 𝑛=0
𝑁−1 𝑁−1
2 2𝑁 − 1 6
𝑏 = 𝑦 𝑛 − 𝑥 𝑛 𝑦 𝑛
𝑁 𝑁+1 𝑁 𝑁+1
𝑛=0 𝑛=0
• Sau, așa cum vom vedea mai târziu, într-o formă matricială ușor de înțeles:
= 𝑎ො = 𝐗 𝑇 𝐗 −1 𝐗 𝑇 𝐲
Θ
𝑏
Exemplu: o linie dreaptă
• Curba albastră este sinusoida originală, iar curba roșie este cea
estimată de punctele verzi
• Estimările sunt prezentate mai sus (valorile reale fiind în paranteze)
Exemplu: sinusoidă
• Cu toate acestea, rezultatele sunt diferite pentru fiecare valoare a zgomotului 𝑤 𝑛
Exemplu: sinusoidă
• Astfel, nu suntem interesați într-un caz individual, ci de
distribuția estimărilor
– Care sunt așteptările: 𝐸 𝑓መ0 , 𝐸 𝜙 și 𝐸 𝐴መ ?
– Care sunt varianțele lor?
– Poate exista o formulă mai bună care ar da o varianță
mai mică?
– Dacă da, cum putem determina estimatorii mai buni?
PROBABILITATE/SIMILARITATE MAXIMĂ
(MAXIMUM LIKELIHOOD)
Estimarea probabilității maxime
• Probabilitatea maximă (MLE) este cea mai populară abordare pentru
estimare datorită aplicabilității sale în probleme de estimare complexe
• Maximizarea probabilității apare deseori ca și criteriu optimal în machine
learning
• Metoda a fost propusă de Fisher în 1922, deși el a publicat principiul de
bază deja în 1912 ca și student în anul 3
• Principiul de bază este simplu: găsim parametrul 𝜃 care este cel mai
probabil să genereze instanța x
• Estimatorul MLE poate sau nu să fie optimal în sensul varianței minime. Nu
este neapărat nici imparțial
Funcția de probabilitate
• Să considerăm din nou problema estimării nivelului mediu A al datelor
zgomotoase
• Presupunem că datele provin din următorul model:
𝑥 𝑛 =𝐴+𝑤 𝑛 ,
unde 𝑤 𝑛 ~𝒩 0, 𝜎 2 : este constant plus un zgomot aleator cu medie
zero și varianță 𝜎 2
Funcția de probabilitate
• Cheia pentru probabilitatea maximă este funcția de
probabilitate (likelihood function)
• Dacă funcția de densitatea a probabilității (PDF) a datelor este
privită ca și o funcție a parametrului necunoscut (cu date fixe),
acesta este numit funcție de probabilitate
• Deseori funcția de probabilitate are o formă exponențială. În
acest sens este uzual să se aplice logaritmul natural pentru a
scăpa de exponent. De notat că maximul noii funcții log-
likelihood (probabilitate logoritmică) nu se schimbă
Funcția de probabilitate
x = np.linspace(2, 8, 200)
likelihood = []
log_likelihood = []
for A in x:
likelihood.append(gaussian(x0, A, 1).prod())
log_likelihood.append(gaussian_log(x0, A, 1).sum())
𝑥 𝑛 −𝐴 =0
𝑛=0
𝑁−1 𝑁−1
𝑥 𝑛 −𝐴=0
𝑛=0 𝑛=0
𝑁−1
𝑥 𝑛 − 𝑁𝐴 = 0
𝑛=0
𝑁−1
𝑥 𝑛 = 𝑁𝐴
𝑛=0
𝑁−1
1
𝐴= 𝑥 𝑛
𝑁
𝑛=0
Concluzie
• Ce anume am realizat?
– Am demonstrat că media exemplelor este estimatorul de
probabilitate maximă pentru media distribuției
• Dar am fi putut ghici acest rezultat de la început. Deci care
este rostul?
– Putem face același lucru pentru cazurile unde nu putem
ghici de la început
Exemplu: estimarea parametrilor sinusoidei
• Considerăm modelul:
𝑥 𝑛 = 𝐴 cos 2𝜋𝑓0 𝑛 + 𝜙 + 𝑤 𝑛
𝐽 𝐴, 𝑓0 , 𝜙 = 𝑥 𝑛 − 𝐴 cos 2𝜋𝑓0 𝑛 + 𝜙 2
𝑛=0
este minimizat
• Minimul acestei funcții poate fi găsit, deși nu este foarte simplu.
• Trecem peste partea de derivare, dar pentru detalii puteți consulta
Kay și alții ”Statistical Signal Processing: Estimation Theory” 1993
Exemplu: estimarea parametrilor sinusoidei
• MLE-ul frecvenței 𝑓0 este obținută prin maximizarea periodogramei peste 𝑓0 :
𝑁−1
ℋ1 : 𝑥 𝑛 = 𝐴 cos 2𝜋𝑓0 + 𝜙 + 𝑤 𝑛
ℋ0 : 𝑥 𝑛 = 𝑤 𝑛
𝑥 𝑛 𝑠 𝑛 > 𝛾′
𝑛=0
Un alt exemplu
• Detectorul pentru un sinusoidal în WGN este:
𝑁−1 𝑁−1
ROC = []
for gamma in np.linspace(0, 1, 1000):
err1 = np.count_nonzero(clf.predict_proba(X_test[y_test == 0, :])[:,1] <= gamma)
err2 = np.count_nonzero(clf.predict_proba(X_test[y_test == 1, :])[:,1] > gamma)
ROC.append([err1, err2])
ROC = np.array(ROC)
ROC = ROC[::-1, :]
auc = roc_auc_score(y_test, clf.predict_proba(X_test)[:,1])
plt.plot(1-ROC[:, 0], ROC[:, 1], linewidth = 2, label="%s (AUC = %.2f)" % (name, auc))
Precision și Recall
• Calcularea PFA din exemplele negative nu este întotdeauna posibilă: De
exemplu, în figurile din dreapta, există milioane de exemple negative
(locații)
• Astfel, în căutare și regăsire, sunt preferați alți metrici:
– Recall-ul (aducerea aminte) unui detector este definit ca proporția de
obiecte adevărate găsite
– Precizia unui detector este proporția de obiecte adevărate din toate
obiectele găsite
• De exemplu, în figura de jos:
– Recall = #obiecte adevărate găsite / #toate obiectele adevărate = 1/1
= 100%
– Precision = #obiecte adevărate găsite / #toate obiectele găsite = 1 / 5
= 20%
Compromisul Precision-Recall
• Deci, putem ajusta sensibilitatea (găsim multe obiecte) și
precizia (găsim doar obiecte adevărate) prin reglarea
pragului de detecție
• Cum am putea să studiem detectorul fără să fim nevoiți să
speculăm despre sensibilitate?
• Acest lucru se poate face prin trasarea graficului precizie
versus recall pentru toate pragurile relevante
• Un exemplu de curbă precision-recall este arătată în dreapta
• Este evident că clasificatorul RF (curba roșie) este superior
clasificatorului SVM (curba albastră)
• Dacă am privi doar la un anumit punct individual de operare
(ex. recall = 0.3, precision = 1.0), am putea să nu vedem
diferența
Precizia Medie
• Curba precision-recall produce o metrică
unică pentru performanța unui detector:
average precision (AP)
• Precizia medie este pur și simplu media
preciziei pentru toate recall-urile
• Aproximativ același cu area under
precision-recall curve
• Detaliile calculelor pot varia, de ex.
pragurile testate efectiv, etc.
Instanța Valoarea Clasa
P1 0.8 1 Un exemplu de trasare a ROC
P2 0.5 1
P3 0.6 0
P4 0.4 0 T = 0.0 PD = 2/2 = 1.0 PFA = 3/3 = 1.0
PFA
Întrebări?
Sisteme de Recunoaștere a Formelor
(Machine Learning & Data Mining)
Curs 04 – Modele Liniare
prof. dr. ing. Robert Győrödi
Sumar
• Clasificare
– Vecini Apropiați
– Liniari
– Analiza discriminantă liniară
– Support Vector Machine
• Regresia
• Scikit-learn
• Set de imagini pentru proiecte ML de la Google
– http://storage.googleapis.com/openimages/web/index.html
Clasificarea
• Multe dintre problemele de machine learning pot fi de tip clasificare
• Multe clasificări pot fi considerate ca și o problemă de partiționare a
spațiului vectorial în regiuni disjuncte
• Aceste probleme constau din următoarele componente:
Exemple: 𝐱 0 , 𝐱 1 , … , 𝐱 𝑁 − 1 ∈ ℝ𝑃
Etichete de clase: 𝑦 0 , 𝑦 1 , … , 𝑦 𝑁 − 1 ∈ 1, 2, … , 𝐶
Clasificator: 𝐹 𝐱 ∶ ℝ𝑃 ↦ 1, 2, … , 𝐶
• Sarcina este de a găsi funcția F care mapează cât mai precis exemplele la
etichetele corespunzătoare
• De exemplu: găsirea funcției F care minimizează numărul de predicții
eronate, ex. cazurile F(x[k]) ≠ y[k]
Regresia
• A doua mare clasă de probleme machine learning constau din regresii
• Pentru regresii, rezultatul este o valoare reală în loc de categorică
• Aceste probleme constau din următoarele componente:
Intrări: 𝐱 0 , 𝐱 1 , … , 𝐱 𝑁 − 1 ∈ ℝ𝑃
Valori țintă: 𝑦 0 , 𝑦 1 , … , 𝑦 𝑁 − 1 ∈ ℝ
Predictor: 𝐹 𝐱 ∶ ℝ𝑃 ↦ ℝ
• De această dată, problema este de a găsi funcția F care mapează cât mai precis exemplele la valorile
corespunzătoare
• De exemplu: găsirea funcției F care minimizează suma pătratelor distanțelor dintre predicții și
valorile țintă:
𝑁−1
2
𝜀 = 𝑦 𝑘 −𝐹 𝐱 𝑘
𝑘=0
Exemplu de clasificare
• De exemplu, considerăm setul de date bi-
dimensionale din dreapta
• Datele constau din 200 de cruciulițe albastre și 200
de cercuri roșii
• Bazat pe aceste date, care ar fi o partiție bună a
spațiului 2D în regiuni ”roșii” și ”albastre”?
• Ce fel de granițe sunt permise între regiuni?
– Linii drepte?
– Granițe continue curbe?
– Granițe fără restricții?
• Notă: În 2D această problemă poate fi rezolvată
manual, dar nu în spații de dimensionalitate mare!
Exemplu de regresie
• De exemplu, considerăm datele 1 dimensionale
din dreapta
• Datele constau din 100 de puncte, unde
coordonata y este funcție de x
• Bazat pe aceste valori, care ar fi a predicție
bună a valorii țintă pentru x = 1.3 (linia
întreruptă)?
• O soluție evidentă este de a potrivi o curbă
peste puncte. Ce fel de formă ar putea avea
această curbă?
– Linie dreaptă?
– Curbe continue?
Diverși Clasificatori
• Vom studia următorii clasificatori folosiți pe scară largă:
– Clasificatorul Vecinului Cel Mai Apropiat
– Clasificatori Liniari (cu graniță liniară)
– Support Vector Machine (cu graniță neliniară)
– Clasificatori de ansamblu: Random Forest
– Cutii negre: Rețele neuronale și rețele neuronale profunde
• Pentru primele patru vom folosi Scikit-Learn https://scikit-learn.org
• Partea despre rețele neuronale va fi studiată cu pachetul Keras
https://keras.io
Scikit-Learn
• Scikit-learn a pornit ca și un proiect Google Summer of Code
• Proiectul a devenit un succes: Exista o nevoie clară pentru o
platformă elegantă gratuită care să aducă împreună metodele
folosite pe scară largă
• În loc ca fiecare contribuitor să ofere propriul pachet, scikit-
learn are un API unificat pentru fiecare metodă
• Pentru detalii: Pedregosa, et al. ”Scikit-learn: Machine
learning in Python”, The Journal of Machine Learning
Research, 2011
Metode Scikit-Learn
• API-ul scikit-learn este intuitiv:
– Inițializare: Fiecare model are propriul constructor, ex.
model = LogisticRegression(penalty = "l1", C = 0.1)
– Antrenare: Fiecare model implementează o metodă .fit(), care antrenează modelul,
ex.
model.fit(X_train, y_train)
– Predicție: Fiecare model implementează o metodă .predict(), care prezice valoare de
ieșire pentru intrări noi, ex.
y_hat = model.predict(X_test)
– Probabilități: Multe modele implementează deasemenea o metodă
.predict_proba(), care prezice probabilitățile de clase pentru intrări noi, ex.
p = model.predict_proba(X_test)
O sesiune exemplu Scikit-learn
# Cod de antrenare: • În codul exemplu, X constă din
from sklearn.linear_model import LogisticRegression 400 de exemple bi-
model = LogisticRegression(solver='lbfgs')
model.fit(X, y) dimensionale din două clase.
# Cod de testare:
>>> model.predict([[2,1]])
array([ 1.])
>>> model.predict([[0,-3]])
array([ 0.])
# Cod de testare:
print(w)
[0.17110018 0.98763186]
print(np.dot(w, [0,-2]) - T)
0.8453404839089127
# Pozitiv -> in clasa "cercuri rosii"
print(np.dot(w, [0,-3]) - T)
-0.1422913780120032
# Negativ -> in clasa "x-uri albastre"
Soluția 3: Scikit-learn
# Cod antrenare: • Scikit-learn implementează LDA într-o
from sklearn.discriminant_analysis
import LinearDiscriminantAnalysis
manieră directă
clf = LinearDiscriminantAnalysis()
• Prima dată construim clasificatorul
# X contine toate exemplele, iar y clasele lor folosind
# etichete: y = [0,1,1,0,...]
clf.fit(X, y)
LinearDiscriminantAnalysis()
• După aceea antrenăm modelul folosind
fit()
# Cod de testare:
print(clf.coef_) # Acesta este vectorul nostru w • După aceea prezicem clasele folosind
[[0.34220035 1.97526372]]
print(clf.intercept_) # Acesta este pragul predict()
[5.64120842]
print(clf.predict([[0, -2]])) • Sau probabilitățile claselor folosind
[1.00000000]
print(clf.predict([[0, -3]]))
predict_proba()
[0.00000000]
print(clf.predict_proba([[0, -3]]))
[[0.57066939 0.42933061]]
LDA Multi-clasă
• LDA poate fi generalizat pentru a trata mai mult de 2
clase
• LDA multiclasă poate fi înțeles în două contexte:
– Ca și reducere de dimensionalitate: Căutăm un
set de proiecții, care reduc dimensionalitatea
datelor reținând totodată separabilitatea
originală
– Ca și clasificare: Căutăm un set de funcții
discriminant care dau un scor de probabilitate
pentru fiecare clasă
• Suntem mai interesați în cea de a doua interpretare
LDA Multi-clasă
• LDA multi-clasă este definită de un set de K funcții liniare
– una pe clasă
𝑔1 𝐱 = 𝐰1𝑇 𝐱 + 𝒘𝟏
⋮
𝑔𝐾 𝐱 = 𝐰𝐾𝑇 𝐱 + 𝒘𝑲
• După care vectorul x este asignat clasei k = 1, 2, ..., K dacă
𝑔𝑘 𝐱 > 𝑔𝑗 𝐱
pentru toate 𝑗 ≠ 𝑘
LDA Multi-clasă
# Cod antrenare:
• Modelul LinearDiscriminantAnalysis() se
import numpy as np aplică și la cazul multi-clasă
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
• Metoda fit() găsește cei trei discriminanți
clf = LinearDiscriminantAnalysis() arătați în graficul de mai jos
# X contine toate exemplele, iar y clasele corespunzatoare
# etichete: y = [1,3,1,2,...]
clf.fit(X, y)
# Cod de testare:
# Afiseaza cei trei discriminanti (linii):
print(clf.coef_)
[[-0.96066517 -0.98532847]
[-1.58373942 0.37636399]
[1.59025287 0.38060280]]
# Calculeaza discriminantii pentru [0,-2]
scores = np.dot(clf.coef_, [0,-2]) + clf.intercept_
print(scores)
[-1.03669054 1.45951335 -5.53009640]
# Clasa rosu (1) are cel mai mare scor
# Prezicem clasa mai usor folosind predict()
print(clf.predict([[0, -2], [0, -4], [4, -6]]))
[1.00000000 0.00000000 2.00000000]
Întrebări?
Sisteme de Recunoaștere a Formelor
(Machine Learning & Data Mining)
Curs 05 – SVM & Regresie Logistică
prof. dr. ing. Robert Győrödi
Sumar
• Clasificare
– Vecini Apropiați
– Liniari
– Analiza discriminantă liniară
– Support Vector Machine
• Regresia
• Scikit-learn
• Set de imagini pentru proiecte ML de la Google
– http://storage.googleapis.com/openimages/web/index.html
Support Vector Machine
• Support Vector Machine (SVM) este
caracterizat prin proprietatea de margine
maximă (maximum margin property)
• Cu alte cuvinte, încearcă să maximizeze
marginea dintre clase
• În exemplul atașat, datele binare sunt
perfect separabile, și SVM setează granița la
mijlocul zonei dintre cele două clase
• Astfel, locația graniței este definită de doar
trei exemple, numiți vectori suport
Support Vector Machine
• Maximizarea marginii M pentru SVM poate fi
caracterizat ca și o problemă de optimizare
maximiz𝑒𝑎𝑧𝑎 𝑀,
𝐰,𝑏, 𝐰 =1
considerând că
𝑦𝑖 𝐱 𝑖𝑇 𝐰 + 𝑏 ≥ 𝑀, 𝑝𝑒𝑛𝑡𝑟𝑢 𝑖 = 1, 2, … , 𝑁
• Aici, 𝑦𝑖 codifică clasa ca și 𝑦𝑖 = −1, 1 , astfel
ultima condiție poate fi rescrisă ca:
𝐱 𝑖𝑇 𝐰 + 𝑏 ≥ 𝑀, 𝑑𝑎𝑐𝑎 𝑦𝑖 = 1
൝ 𝑇
𝐱 𝑖 𝐰 + 𝑏 ≤ −𝑀, 𝑑𝑎𝑐𝑎 𝑦𝑖 = −1
Support Vector Machine
• Alternativ, criteriul SVM poate fi simplificat într-o formă echivalentă
minimizeaza 𝐰 ,
𝐰,𝑏
considerând că
𝑦𝑖 𝐱 𝑖𝑇 𝐰 + 𝑏 ≥ 1, 𝑝𝑒𝑛𝑡𝑟𝑢 𝑖 = 1, 2, … , 𝑁
• Aceasta este o problemă de optimizare convexă cu constrângeri.
Există algoritmi eficienți specifici.
• Implementarea din Scikit-learn este bazată pe librăria larg folosită
LibSVM
Support Vector Machine
• Definiția anterioară a SVM presupune că clasele sunt separate
(și există o margine între clase)
• În realitate trebuie să permitem anumite exemple să fie pe
partea greșită a marginii
• Soluția este de a penaliza pentru exemple aflate pe partea
greșită
• Funcția rezultată a fi minimizată este:
𝑁
minimizeaza max 0, 1 − 𝑦𝑖 𝐰 𝑇 𝐱 𝑖 + 𝑏 +𝐶 𝐰 2
𝐰,𝑏
𝑖=1
• Pentru fiecare exemplu pe partea greșită, adăugăm o
penalizare (numită hinge loss) definit ca 𝑚𝑎𝑥 0, 𝑥
• De notat că aceasta crește numărul de VS-uri
SVM în Scikit-learn
• Parametrul C determină balanța dintre lățimea marginii și penalizarea
pentru a fi pe partea greșită
• De la stânga la dreapta: SVM-uri liniare cu penalizare descrescătoare
Artificiu cu Nucleu (Kernel Trick)
• SVM-ul poate fi extins la granițe neliniare folosind un artificiu
numit kernel trick
• Artificiul mapează datele într-o dimensionalitate mai mare și
proiectează SVM-ul liniar acolo
• De exemplu, graficul de sus poate fi generat după cum
urmează:
– Mapăm exemplele 2D în 3D: 𝑥, 𝑦 ↦ 𝑥 2 , 𝑦 2 , 2𝑥𝑦
– Antrenăm SVM-ul cu noile exemple 3D
– Granița de decizie este liniară în 3D, dar neliniare în 2D
• Însă, această transformare este înceată; artificiul cu nucleu
face același lucru implicit
Artificiu cu Nucleu (Kernel Trick)
• Poate fi arătat că substituția produsului punct printr-o anumită
funcție neliniară este echivalentă unei mapări explicite
• Mai specific, un algoritm poate fi nucleificat (kernelized) prin
inserarea unei funcții nucleu 𝜅 𝐱, 𝐲 în loc de produsul punct 𝐱 ⋅ 𝐲
• Poate fi arătat că în anumite condiții pe nucleu (ex. semidefinire
pozitivă), aceasta este echivalentă cu o mapare explicită
• Au fost realizate multe cercetări asupra relației unui nucleu și
maparea corespunzătoare
• Însă, vom lua o abordare mai practică și considerăm un exemplu
Artificiu cu Nucleu (Kernel Trick)
• Ca și un exemplu, examinăm ce se întâmplă când produsul
intern a vectorilor 2D 𝐱 = 𝑥1 , 𝑥2 și 𝐲 = 𝑦1 , 𝑦2 este înlocuit
cu pătratul acestora:
𝜅 𝐱, 𝐲 = 𝐱 ⋅ 𝐲 𝟐
• Putem extinde nucleul:
𝜅 𝐱, 𝐲 = 𝐱 ⋅ 𝐲 𝟐
= 𝑥1 𝑦1 + 𝑥2 𝑦2 2
= 𝑥1 𝑦1 2 + 𝑥2 𝑦2 2 + 2𝑥1 𝑦1 𝑥2 𝑦2
Artificiu cu Nucleu (Kernel Trick)
# Cod de testare:
print(clf.coef_) # Acesta este vectorul nostru w vector (cazul liniar)
[[0.73439694 0.28806980]]
print(clf.intercept_) # Acesta este pragul
[1.63787568]
print(clf.predict([[-4,-2], [-2,0]]))
[0.00000000 1.00000000]
print(clf.support_vectors_)
[[-2.40000000 -3.04024390]
[-0.38544996 -1.23082179]
[0.41606392 -3.27417889]]
SVM Multi-clasă
• SVM este inerent pentru două clase
• Generalizarea pentru mai multe clase este realizată prin
compararea de perechi de clase
• Pentru fiecare clasă, antrenăm un SVM care clasifică această clasă
versus toate celelalte
• Scikit-learn oferă câteva meta-clasificatori pentru acest lucru
– multiclass.OneVsRestClassifier compară fiecare clasă
vs. toate celelalte (necesită K clasificatori)
– multiclass.OneVsOneClassifier compară toate perechile
de clase (necesită K(K – 1)/2 clasificatori)
SVM Multi-clasă
• O extensie suplimentară este clasificarea multietichetă, unde
mai multe clase pot fi prezente simultan
• Țintele sunt prezentate ca și indicatori binari:
from sklearn.preprocessing import MultiLabelBinarizer
yc = [[2, 3, 4], [2], [0, 1, 3], [0, 1, 2, 3, 4], [0, 1, 2]]
MultiLabelBinarizer().fit_transform(yc)
array([[0, 0, 1, 1, 1], # Clasele 2,3,4 sunt "prezente"
[0, 0, 1, 0, 0], # Clasa 3 este "prezenta"
[1, 1, 0, 1, 0], # ...
[1, 1, 1, 1, 1],
[1, 1, 1, 0, 0]])
# Cod de testare:
print(clf_ova.predict(np.array([[2,-3.4], [4,-2]])))
[0.00000000 2.00000000]
print(clf_ovo.predict(np.array([[2,-3.4], [4,-2]])))
[1.00000000 2.00000000]
print(len(clf_ova.estimators_))
3
Regresia Logistică
• Al treilea membru a familiei de clasificatori liniari este Regresia Logistică
(LR)
• Spre deosebire de celelalte două, LR este probabilistic, adică modelează
probabilitățile claselor în loc de apartenența simplă la o clasă
• Pentru cazul cu două clase (𝑐 ∈ 0, 1 ), modelul este:
1
𝑝 𝑐=1𝐱 =
1 + exp − 𝐰 𝑇 𝐱 + 𝑏
• De asemenea: 𝑝 𝑐 = 0 𝐱 = 1 − 𝑝 𝑐 = 1 𝐱
• În esență, modelul mapează proiecția 𝐰 𝑇 𝐱 + 𝑏 prin funcția sigmoid (astfel
limitând intervalul la [0, 1]).
Regresia Logistică
• Modelul este ilustrat aici:
– Exemplele sunt proiectate în 1D
folosind ponderile învățate w și b
– ”Scorurile de clasă” rezultate sunt
mapate prin funcția logistică, care
transformă scorurile în
probabilități 𝑝 𝑐 = 1 𝐱 ∈ 0,1
• Estimările de probabilitate pot fi de
asemenea mapate înapoi în 2D, așa
cum este arătat în figura din dreapta
Antrenarea modelelor de regresie logistică
• Regresia logistică este antrenată prin probabilitatea maximă
• Cu alte cuvinte, maximizăm probabilitatea de observare a acestor puncte
corespunzător parametrilor modelului
• Probabilitatea exemplelor 𝐗 = 𝐱 0 , 𝐱1 , … , 𝐱 𝑁−1 cu etichetele de clasă
𝑦0 , 𝑦1 , … , 𝑦𝑁−1 ∈ 1,2, … , 𝐾 să fi apărut din modelul cu parametri 𝜃 este
𝑁−1
𝑝 𝐗 𝜃 = ෑ 𝑝 𝐱 𝑛 ; 𝜃, 𝑦𝑛
𝑛=0
• Ca de obicei, considerăm o probabilitate logaritmică în loc:
𝑁−1
ln 𝑝 𝐗 𝜃 = ln 𝑝 𝐱 𝑛 ; 𝜃, 𝑦𝑛
𝑛=0
Antrenarea modelelor de regresie logistică
• Pentru simplitate, vom continua doar cu cazul a două
clase
• Să etichetăm clasele ca 𝑦𝑘 ∈ −1,1 , deoarece astfel
simplificăm notația pentru mai târziu
• De asemenea: să ascundem termenul constant b prin
concatenarea la sfârșitul w:
𝐰 ← 𝐰, 𝑏 și 𝐱 ← 𝐱, 1
Antrenarea modelelor de regresie logistică
• Probabilitățile claselor -1 și 1 sunt acum:
1
𝑝 𝐱 𝑛 𝑦𝑛 = 1 =
1 + exp −𝐰 𝑇 𝐱 𝑛
1
𝑝 𝐱 𝑛 𝑦𝑛 = −1 = 1 −
1 + exp −𝐰 𝑇 𝐱 𝑛
1 + exp −𝐰 𝑇 𝐱 𝑛 − 1
=
1 + exp −𝐰 𝑇 𝐱 𝑛
exp −𝐰 𝑇 𝐱 𝑛
=
1 + exp −𝐰 𝑇 𝐱 𝑛
1 1
= =
exp 𝐰 𝑇 𝐱 𝑛 + 1 1 + exp 𝐰 𝑇 𝐱 𝑛
Antrenarea modelelor de regresie logistică
• 𝑝 𝐱𝑛 𝑦𝑛 = 1 și 𝑝 𝐱𝑛 𝑦𝑛 = −1 sunt aproape aceeași formă
și pot fi combinate într-o singură formulă:
1
𝑝 𝐱 𝑛 𝑦𝑛 =
1 + exp −𝑦𝑛 𝐰 𝑇 𝐱𝑛
• Probabilitatea pentru toate exemplele 𝐗 = 𝐱0 , 𝐱1 , … , 𝐱𝑁−1
este acum:
𝑁−1
1
𝑝 𝐗 𝐰, 𝐲 = ෑ
1 + exp −𝑦𝑛 𝐰 𝑇 𝐱 𝑛
𝑛=0
Antrenarea modelelor de regresie logistică
ln 𝑝 𝐗 𝐰, 𝐲 = ln 1 − ln 1 + exp −𝑦𝑛 𝐰 𝑇 𝐱 𝑛
𝑛=0
𝑁−1
= − ln 1 + exp −𝑦𝑛 𝐰 𝑇 𝐱 𝑛
𝑛=0
Antrenarea modelelor de regresie logistică
• Pentru a maximiza probabilitatea, putem minimiza la fel și funcția de pierdere
logistică (logistic loss function)
𝑁−1
ℓ 𝐰 = ln 1 + exp −𝑦𝑛 𝐰 𝑇 𝐱 𝑛
𝑛=0
• Există mai mulți algoritmi pentru minimizarea pierderii logistice, ex:
– Iterative Reweighted Least Squares (IRLS) este un algoritm calibrat special
pentru astfel de probleme. Folosit de statsmodels.api.Logit și
statsmodels.api.MNLogit
– Abordări bazate pe teoria optimizării. Deoarece ln 𝑝 𝐗 𝜃 este convex, în
principiu se poate folosi orice abordare de optimizare. Scikit-learn
folosește ceva numit Trust Region Newton Algorithm
Antrenarea modelelor de regresie logistică
• Abordarea bazată pe teoria optimizării a devenit dominantă, pentru două motive:
1. Antrenarea SVM poate fi pusă în același cadru: minimizarea hinge loss:
hinge_loss = max 0,1 − 𝑦𝑛 𝐰 𝑇 𝐱 𝑛
2. Un optimizator generic poate minimiza de asemenea și pierderile
modificate. Mai important, putem adăuga un termen de penalizare în
funcția de pierdere; ex.
𝑁−1
• Cu alte cuvinte: este un model de regresie logistică, iar întreaga rețea este pur și
simplu o stivă de modele logreg
Antrenarea Rețelei
• În trecut, a fost un accent destul de mare pe
algoritmii de antrenare: gradient conjugat,
Levenberg-Marquardt, etc.
• Astăzi, optimizatoarele sunt mai puțin matematici:
stohastic gradient descent, RMSProp, Adam
Backpropagation
• Rețeaua este antrenată prin ajustarea ponderilor
corespunzător cu derivatele parțiale
𝜕ℇ
𝑤𝑖𝑗 ← 𝑤𝑖𝑗 − 𝜂
𝜕𝑤𝑖𝑗
• Cu alte cuvinte, ponderea a j-a a nodului al i-lea
trece spre gradientul negativ cu pasul 𝜂 > 0
• În anii 1990 structura rețelei era destul de fixă și
formula era derivată manual
• Astăzi, se aplică același principiu, dar forma
exactă este calculată simbolic
Backpropagation în Haykin:
Neural networks, 1999
Înainte și Înapoi
• Antrenarea are două treceri: pasul înainte și pasul înapoi
• Pasul înainte alimentează rețeaua cu una (sau mai multe) exemple
• Pasul înapoi calculează eroarea (medie) și propagă gradienții înapoi ajustând ponderile una câte una
• Când rețeaua a fost alimentată cu toate exemplele, a trecut o epocă. În mod tipic rețeaua rulează
pentru mii de epoci
Pachete Software pentru Rețele Neuronale
• Tensorflow: Motor de deep learning de la Google. A fost deschis în 2015 noiembrie.
– Suportat de Keras, care este integrat cu TF de la versiunea 2.0 a TF
• MS Cognitive TK (CNTK): Motor de deep learning de la Microsoft.
– Suportat de Keras
• mxnet: Deep learning scalabil (ex. Android). Primul în multi-gpu. Mulți contributori.
– Suportat de Keras
• PlaidML: Backend OpenCL.
– Suportat de Keras
• Torch: Librărie implementată în limbajul Lua (Facebook). Interfață Python via pyTorch
https://towardsdatascience.com/deep-
https://madhav.run/tag/c/ learning-framework-power-scores-2018-
23607ddf297a
Antrenarea unei rețele cu 2 nivele folosind Keras
# Cod de antrenare:
import tensorflow as tf
# Cod de testare:
# Probabilitati
print(clf.predict(np.array([[1, -2], [-3, -5]])))
[[0.5212911]
[0.4997456]]
# Clase
print(clf.predict(np.array([[1, -2], [-3, -5]])) > 0.5)
[[ True]
[False]]
Deep Learning
• Cercetarea în domeniul rețelelor neuronale a fost destul de redus după rapida
expansiune din anii 1990
• Subiectul fierbinte al anilor 2000 au fost SVM și big data
• Totuși, la sfârșitul decadei, rețelele neuronale au început să câștige în
popularitate din nou: Un grup de la Univ. Toronto, condus de Prof. Geoffrey
Hinton a studiat rețele adânci neconvenționale folosind pre-antrenare ne-
supervizată
• Ei au descoperit că antrenarea unor rețele neuronale mari este într-adevăr
posibilă cu un pas de pre-antrenare nesupervizată care inițializează ponderile
rețelei într-o manieră pe nivele
• Un alt factor cheie pentru succes a fost creșterea rapidă a puterii
computaționale aduse de Unitățile de Procesare Grafică (GPU) recente
Pre-antrenare Nesupervizată
• Au existat două probleme principale pentru cauza limitării la 2-3 nivele a rețelelor neuronale:
1. Eroarea are zone de minim local mari pentru rețele adânci: Antrenarea rămâne blocată la
una dintre acestea
2. Gradientul dispare la nivelele inferioare: Funcția de activare logistică tinde să scadă
magnitudinea gradientului la fiecare nivel; eventual gradientul la nivelele inferioare este
foarte mic astfel acestea nu se mai antrenează deloc
• Acum 10 ani s-a descoperit că ambele probleme pot fi corectate prin pre-antrenare ne-supervizată:
– Antrenarea modelelor pe nivele care au învățat să reprezinte datele (fără etichete de clase, fără
clasificare, doar să încerce să învețe să reproducă datele)
– Inițializarea rețelei cu ponderi ale modelului ne-supervizat și antrenează într-un mod
supervizat
– Unelte uzuale: restricted Boltzmann machine (RBM), deep belief network (DBN), autoencoders,
etc.
Înapoi la Antrenarea Supervizată
• După ce s-a declanșat entuziasmul pentru rețele adânci, a pornit și studiul
abordărilor total supervizate (antrenarea pur supervizată este mai
familiară, bine explorată și o abordare mai puțin înfricoșată)
• Câteva descoperiri cheie evită nevoia pre-antrenării:
– Funcții noi de activare care conservă mai bine gradientul peste nivele;
cel mai important Rectified Linear Unita: ReLU(x)=max(0,x).
– Tehnici inedite de inițializare a ponderilor; ex. inițializarea Glorot
(inițializarea Xavier) ajusetază magnitudinea ponderilor inițiali pe
niveleb.
– Regularizarea dropout (lăsarea pe dinafară); evitarea supra-potrivirii
prin injectarea de zgomot în rețeac. Neuroni individuali sunt opriți
aleator în faza de antrenare.
aGlorot, Bordes și Bengio. ”Deep sparse rectifier neural networks”
bGlorot și Bengio. ”Understanding the difficulty of training deep feedforward neural networks”
cSrivastava, Hinton, Krizhevsky, Sutskever și Salakhutdinov. ”Dropout: A simple way to prevent neural networks from overfitting”
Nivele Convoluționale
• În plus față de tehnicile inovative pentru antrenare, au
fost adoptate și noi arhitecturi de rețele
• Cel mai important dintre acestea este nivelul
convoluțional, care conservă topologia intrărilor
• Rețele convoluționale au fost propuse deja în 1989, dar
au avut un rol destul de marginal cât timp dimensiunile
imaginilor erau mici (ex. setul de date MNIST din 1990
are dimensiunile 28 x 28, comparat cu referința curenta
ImageNet cu dimensiunea 256 x 256)
Rețele Convoluționale
• Structura tipică a unei rețele convoluționale repetă următoarele elemente:
convoluție neliniaritate subeșantionare
1. Convoluția filtrează intrarea cu un număr de nuclee convoluționale. În primul nivel acestea
pot fi, ex. 9 x 9 x 3; adică acestea văd o fereastră locală pentru toate nivelele RGB
• Rezultatele sunt numite feature maps și în mod tipic sunt o mulțime de acest fel
2. ReLU transmite hărțile de caracteristici printr-un Rectified Linear Unit pe pixeli
• ReLU(x) = max(0, x)
3. Subeșantionarea contractă dimensiunile de intrare printr-un factor întreg
• Original acest lucru a fost realizată prin medierea fiecărui bloc 2 x 2
• Astăzi, maxpooling este mai folosit (preia maximul fiecărui bloc 2 x 2)
• Subeșantionarea reduce dimensiunea datelor și îmbunătățește invarianța spațială
Rețele Convoluționale: Exemple
• Hai să antrenăm un convnet cu faimosul set de date
MNIST
• MNIST constă din 60000 imagini de antrenare și 10000
imagini de testare, reprezentând numere scrise de mână
de la poșta SUA
• Fiecare imagine are 28 x 28 pixeli și sunt 10 categorii
• În general este considerat o problemă ușoară: Regresia
logistică oferă o acuratețe de peste 90% iar convnet
poate atinge (aproape) 100%
• Totuși, acum 10 ani, cea mai bună eroare era încă peste
1%
Rețele Convoluționale: Exemple
# Cod de antrenare model = Sequential()
from tensorflow.keras.datasets import mnist # Layer 1: necesita si input_shape.
from tensorflow.keras.models import Sequential model.add(Conv2D(num_featmaps, (w, h),
from tensorflow.keras.layers import Dense, Activation, Flatten, input_shape=(28, 28, 1),
Conv2D, MaxPooling2D activation = 'relu'))
from tensorflow.keras.utils import to_categorical
import numpy as np # Layer 2:
import os model.add(Conv2D(num_featmaps, (w, h), activation = 'relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
# Folosim baza de date de cifre scrise de mana "MNIST".
# 60000 imagini de antrenare si 10000 imagini de testare # Layer 3: nivel dens cu 128 noduri
# cu dimensiunea 28x28 # Flatten() vectorizeaza datele: 32x10x10 -> 3200
(X_train, y_train), (X_test, y_test) = mnist.load_data() # (10x10 in loc de 14x14 datorita efectului de margine)
model.add(Flatten())
# Keras presupune intrare 4D, dar MNIST nu are canalul de culoare. model.add(Dense(128, activation = 'relu'))
# -> Adaugam o dimensiune falsa la capat.
X_train = X_train[..., np.newaxis] / 255.0 # Layer 4: Ultimul nivel producand 10 iesiri.
X_test = X_test[..., np.newaxis] / 255.0 model.add(Dense(num_classes, activation='softmax'))
– Încărcarea:
from tensorflow.keras.models import load_model
load_model('my_net.h5')
• Rețeaua este salvată în formatul HDF5. HDF5 este un format de serializare similar .mat sau .pkl, dar mult mai eficient
• Folosim HDF5 pentru stocarea datelor cu h5py
# Salvare np.array X in fisier h5:
import h5py
with h5py.File('my_data.h5', 'w') as h5:
h5['X'] = X
procesare
• Proiectată prin arătarea
de exemple
• Exemple:
Recunoașterea imaginilor
• Imagenet este setul de imagini de
referință standard pentru
recunoașterea imaginilor
• Clasificarea unor imagini 256x256 în
1000 de categorii, cum ar fi
”persoană”, ”bicicletă”, ”animal”, etc.
• În total 1.3M imagini
• Multe metrici pentru erori, incluzând
top-5 erori: rata erorii cu 5 estimări
ImageNet classification with deep convolutional neural networks
Alex Krizhevsky et al., 2012
Computer Vision
• Folosit pentru logistică din 1994
• Plăcuțe de înmatriculare (LRP), coduri containere, ...
• Cum se poate crește într-un mediu cu competiție acerbă?
– Agil
– Inovativ
– Credibil
– Orientat spre client
– Folosind tehnologie de vârf
Ce s-a schimbat în 20 de ani?
• În 1996: • În 2016:
– Imagini mici (10x10) – Imagini mari (256x256)
– Puține clase (< 100) – Multe clase (> 1K)
– Rețele mici (< 4 nivele) – Rețele adânci (> 100 kerrosta)
– Date puține (< 50K imagini) – Date multe (> 1M imagini)
Evoluția adâncimii rețelelor din 2012
• ILSVRC Image Recognition Task
– 1.3 milioane imagini
Echipa Anul Loc Eroare Nivele
– 1000 categorii (top-5)
SuperVision 2012 1 15.30% 8
https://ai.googleblog.com/2017/11/automl-for-large-scale-image.html Sandler et. al. ”MobileNetV2: Inverted Residuals and Linear Bottlenecks”, 2018
ILSVRC2015
• Câștigător MSRA (Microsoft Research)
cu eroarea top-5 3.57%
• 152 nivele! 51M parametri
• Construit din blocuri reziduale (care
includ trucul de inițializare din anul
precedent)
• Idea principală este de a adăuga
scurtături de identitate, care fac
antrenarea mai ușoară
# Adaugam sase nivele convolutionale. Adaugam cate un nivel Maxpool dupa fiecare a doua convolutie.
model.add(Conv2D(filters=32, kernel_size=3, padding="same", activation="relu", input_shape=shape))
model.add(Conv2D(filters=32, kernel_size=3, padding="same", activation="relu"))
model.add(MaxPooling2D(2, 2)) # Micsoram caracteristicile la 32x32
model.compile(loss='sparse_categorical_crossentropy',
optimizer=tf.keras.optimizers.Adam(0.001),
metrics=['accuracy'])
model.fit(
ds_train,
epochs=6,
validation_data=ds_test
)
Întrebări?
Sisteme de Recunoaștere a Formelor
(Machine Learning & Data Mining)
Curs 08 – Data Mining
prof. dr. ing. Robert Győrödi
What is Data Mining?
• Knowledge discovery from data
• Churn analysis
• Cross-selling
• Fraud detection
• Risk management
• Customer segmentation
• Targeted ads
• Sales forecast
Domain
• Machine Learning
– Is a scientific discipline that explores the construction and study of algorithms that can learn from data
– In particular you can use Machine Learning algorithms to predict future trends, better structure your
knowledge in a certain domain and gain some meaningful business insights
• In Supervised Learning scenarios you will typically know exactly what you are trying to predict
– For example, numerical or non-numerical values predictions
• Regression
• Classification
• In Unsupervised Learning scenarios you may be lacking a good enough understanding of the problem
domain, in fact typically knowing roughly what you may be looking for, thus you may be relying on the
system to provide some hints to gain a better understanding of the problem domain
– For example, grouping info in logical way or detecting deviations from normal system behaviour
• Clustering
• Anomaly detection
Machine
Learning
Domain
Supervised Unsupervised
Learning Learning
Anomaly
Regression Classification Clustering
Detection
Microsoft Azure
https://searchcloudcomputing.techtarget.com/definition/Windows-Azure
• Threshold
Understanding ROC and AUC
• The receiver operating
characteristics (ROC) graph is a two-
dimensional graph in which the true
positive rate (TP) is plotted on the y axis
and the false positive rate (FP) is plotted on
the x axis.
• Decision tree
– A flow-chart-like tree structure
– Internal node denotes a test on an attribute
– Branch represents an outcome of the test
– Leaf nodes represent class labels or class distribution
• Decision tree generation consists of two phases
– Tree construction
• At start, all the training examples are at the root
• Partition examples recursively based on selected attributes
– Tree pruning
• Identify and remove branches that reflect noise or outliers
• Use of decision tree: Classifying an unknown sample
– Test the attribute values of the sample against the decision tree
Training Dataset
• This follows an example from Quinlan’s ID3
age income student credit_rating buys_computer
<=30 high no fair no
<=30 high no excellent no
31…40 high no fair yes
>40 medium no fair yes
>40 low yes fair yes
>40 low yes excellent no
31…40 low yes excellent yes
<=30 medium no fair no
<=30 low yes fair yes
>40 medium yes fair yes
<=30 medium yes excellent yes
31…40 medium no excellent yes
31…40 high yes fair yes
>40 medium no excellent no
Output: A Decision Tree for
“buys_computer”
age?
no yes no yes
Algorithm for Decision Tree Induction
• Thus, this has the greater gain (1.389898 > 0.321928), and
we choose this over gender as the first splitting attribute
DT Example (5)
Height
<=1.6m >2.0m
• Find the frequent itemsets: the sets of items that have minimum
support
– A subset of a frequent itemset must also be a frequent itemset
• i.e., if {AB} is a frequent itemset, both {A} and {B} should be a frequent itemset
– Iteratively find frequent itemsets with cardinality from 1 to k (k-itemset)
• Use the frequent itemsets to generate association rules.
The Apriori Algorithm
• Join Step: Ck is generated by joining Lk-1with itself
• Prune Step: Any (k-1)-itemset that is not frequent cannot be a subset of a
frequent k-itemset
• Pseudo-code:
Ck: Candidate itemset of size k
Lk : frequent itemset of size k
L1 = {frequent items};
for (k = 1; Lk !=; k++) do begin
Ck+1 = candidates generated from Lk;
for each transaction t in database do
increment the count of all candidates in Ck+1 that are contained in t
Lk+1 = candidates in Ck+1 with min_support
end
return k Lk;
The Apriori Algorithm — Example
Database D itemset sup.
L1 itemset sup.
TID Items C1 {1} 2 {1} 2
100 134 {2} 3 {2} 3
200 235 Scan D {3} 3 {3} 3
300 1235 {4} 1 {5} 3
400 25 {5} 3
C2 itemset sup C2 itemset
L2 itemset sup {1 2} 1 Scan D {1 2}
{1 3} 2 {1 3} 2 {1 3}
{2 3} 2 {1 5} 1 {1 5}
{2 3} 2 {2 3}
{2 5} 3
{2 5} 3 {2 5}
{3 5} 2
{3 5} 2 {3 5}
C3 itemset Scan D L3 itemset sup
{2 3 5} {2 3 5} 2
How to Generate Candidates?
• Suppose the items in Lk-1 are listed in an order
• Step 1: self-joining Lk-1
insert into Ck
select p.item1, p.item2, …, p.itemk-1, q.itemk-1
from Lk-1 p, Lk-1 q
where p.item1=q.item1, …, p.itemk-2=q.itemk-2, p.itemk-1 < q.itemk-1
• Step 2: pruning
forall itemsets c in Ck do
forall (k-1)-subsets s of c do
if (s is not in Lk-1) then delete c from Ck
How to Count Supports of Candidates?
• Pruning:
– acde is removed because ade is not in L3
• C4={abcd}
Methods to Improve Apriori’s Efficiency