Applicazioni pratiche di machine learning/Trovare lavoro

Indice del libro

Caricamento librerie

modifica
 library(dplyr)
 library(ggplot2)
 library(statsr)

Parte 1: Dati

modifica

Il dataset Job_Placement_Data.csv scaricabile da kaggle contiene 215 records di 13 variabili, relativi a neolaureati assunti o non assunti (placed or not placed) . Si vogliono evidenziare i fattori che influenzano positivamente l'assunzione di un candidato. Ecco la spiegazione sulle variabili:

  • gender: sesso del candidato
  • ssc_percentage: percentuale dei voti di scuola media
  • ssc_board: Consiglio didattico per gli esami ssc
  • hsc_percentage: percentuale dei voti di scuola superiore
  • hsc_board: consiglio didattico per gli esami hsc
  • hsc_subject: oggetto di studio per hsc (arte, commercio, scienza)
  • Degree_percentage: percentuale dei voti ottenuti nella laurea
  • undergrad_degree: titoli di studio universitari
  • work_experience: esperienza lavorativa passata
  • emp_test_percentage: percentuale del test attitudinale
  • specialization: specializzazioni post-laurea - (specializzazione MBA)
  • mba_percent: percentuale dei voti in Master Business Administration
  • status (TARGET): stato del posizionamento. Posizionato/Non posizionato

Caricamento dati:

Job_Placement_Data <- read.csv("Job_Placement_Data.csv")

Parte 2 : Domanda di ricerca

modifica

Si vuole evidenziare che a prescindere dall'esperienza lavorativa, se le medie dei voti della scuola inferiore, superiore, laurea, test attitudinali, master del candidato sono alte, il candidato tende a trovare lavoro. Chi ha esperienza lavorativa ma voti scolastici bassi tende ad essere disoccupato. Inoltre non dipende dal tipo di studi (arte, commercio, scienze) se il candidato lavora oppure no. Per finire si vuole predire se un candidato troverà lavoro in base alle altre variabili.

Parte 3 : Esplorazione dati

modifica

In chi è occupato la media di percentuale di voti nella scuola inferiore, superiore, università, master risulta di molto maggiore rispetto a chi non è occupato:


Job_Placement_Data %>%
  group_by(status) %>%
  summarise(media_scuola_inferiore=mean(ssc_percentage),
            media_scuola_superiore=mean(hsc_percentage),
            media_voti_laurea=mean(degree_percentage),
            media_test_attitudinale=mean(emp_test_percentage),
            media_master_mba=mean(mba_percent))
A tibble: 2 × 6

status media_scuola_inferiore media_scuola_superiore media_voti_laurea media_test_attitudinale media_master_mba

1 Not Placed      57.5                   58.4              61.1       69.6    61.6
2 Placed          71.7                   69.9              68.7       73.2    62.6

Come si vede dal seguente grafico e dal t test, chi ha esperienza lavorativa è in proporzione più occupato di chi non ce l'ha, infatti nel t test, essendo p_value<0,05, non vale l'ipotesi nulla al 95%, secondo cui la percentuale di chi è occupato sarebbe la stessa di chi non lo è:

Job_Placement_Data %>%
  group_by(status,work_experience) %>%
  summarise(totale=n(), .groups = "keep") %>%
  ggplot(aes(status,totale, fill=work_experience))+
  geom_bar(stat = "identity")
 
inference(work_experience, status, data=Job_Placement_Data,statistic = "proportion",method = "theoretical", alternative = "less", type = "ht", success = "Yes", null = 0)
Response variable: categorical (2 levels, success: Yes)
Explanatory variable: categorical (2 levels) 
n_Not Placed = 67, p_hat_Not Placed = 0.1493
n_Placed = 148, p_hat_Placed = 0.4324
H0: p_Not Placed =  p_Placed
HA: p_Not Placed < p_Placed
z = -4.0478
p_value = < 0.0001


Come si vede dalla seguente tabella la media delle percentuali di voti nella scuola inferiore, superiore, università e master risulta di molto maggiore in chi ha esperienza lavorativa ed è occupato rispetto a chi ha esperienza ma risulta non occupato:

Job_Placement_Data %>%
  group_by(status, work_experience) %>%
  summarise(media_scuola_inferiore=mean(ssc_percentage),
            media_scuola_superiore=mean(hsc_percentage),
            media_voti_laurea=mean(degree_percentage),
            media_test_attitudinale=mean(emp_test_percentage),
            media_master_mba=mean(mba_percent), .groups = "keep")
A tibble: 4 × 7
# Groups:   status, work_experience [4]
status    work_experience media_scuola_inferiore media_scuola_superiore media_voti_laurea media_test_attitudin… media_master_mba
1 Not Placed No  58.1          58.1              61.3          70.4             61.4
2 Not Placed Yes 54.2          59.8              60.2          65.2             62.7
3 Placed    No   71.2          70.0              68.7          72.4             61.7
4 Placed    Yes  72.4          69.8              68.8          74.4             63.8

Come si vede dal seguente t test oltre che dalla precedente tabella, tra gli occupati la percentuale di voti alla scuola superiore di chi ha esperienza lavorativa è in media la stessa di chi non ha esperienza, infatti vale l'ipotesi nulla al 95%, essendo p_value>0,05 . Lo stesso vale per altre scuole: inferiore, università, master.


df_placed <- Job_Placement_Data %>%
  filter(status=="Placed")

inference(hsc_percentage,work_experience, data=df_placed,statistic = "mean",method = "theoretical", alternative = "twosided", type = "ht", null = 0)
Response variable: numerical
Explanatory variable: categorical (2 levels) 
n_No = 84, y_bar_No = 70.0248, s_No = 9.4334
n_Yes = 64, y_bar_Yes = 69.7977, s_Yes = 9.2636
H0: mu_No =  mu_Yes
HA: mu_No != mu_Yes
t = 0.1466, df = 63
p_value = 0.8839


Non dipende dal tipo di studi (arte, commercio, scienze) se il candidato lavora oppure no infatti nel seguente test chi quadrato p_value>0,05 quindi le 2 variabili status e hsc_subject sono indipendenti:

inference(status,hsc_subject, data=Job_Placement_Data, statistic = "proportion",method = "theoretical", alternative = "greater", type = "ht", success = "Placed")
Response variable: categorical (2 levels) 
Explanatory variable: categorical (3 levels) 
Observed:
            y
x          Not Placed Placed
 Arts              5      6
 Commerce         34     79
 Science          28     63
Expected:
           y
x          Not Placed    Placed
 Arts       3.427907  7.572093
 Commerce  35.213953 77.786047
 Science   28.358140 62.641860
H0: hsc_subject and status are independent
HA: hsc_subject and status are dependent
chi_sq = 1.1147, df = 2, p_value = 0.5727


Parte 4 : Modellizzazione e Previsione in Python

modifica
import pandas as pd

# Read the data
data = pd.read_csv('Job_Placement_Data.csv')
from sklearn.model_selection import train_test_split

# Separo la variabile target dalle variabili predictors
y = data.status
X = data.drop(['status'], axis=1)

# Divido i dati in training (75%) e validation (25%) sets
X_train_full, X_valid_full, y_train, y_valid = train_test_split(X, y, train_size=0.75, test_size=0.25,random_state=0)

# 
# Seleziono le colonne contenenti variabili categoriche 
categorical_cols = [cname for cname in X_train_full.columns if X_train_full[cname].nunique() < 10 and 
                        X_train_full[cname].dtype == "object"]

# Seleziono le colonne contenenti variabili numeriche
numerical_cols = [cname for cname in X_train_full.columns if X_train_full[cname].dtype in ['int64', 'float64']]

# Seleziono nel dataset tali colonne
my_cols = categorical_cols + numerical_cols
X_train = X_train_full[my_cols].copy()
X_valid = X_valid_full[my_cols].copy()
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler

# Standardizzo le colonne numeriche
numerical_transformer = StandardScaler()

# Trasformo le colonne categoriche in numeriche e attribuisco un valore frequente ai NA 
categorical_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='most_frequent')),
    ('onehot', OneHotEncoder(handle_unknown='ignore')),
    
])

preprocessor = ColumnTransformer(
    transformers=[
        ('num', numerical_transformer, numerical_cols),
        ('cat', categorical_transformer, categorical_cols)
    ])


Alleno sul training set vari algoritmi di machine learning. Quello con la migliore accuracy sul validation set (83,33%) è LinearDiscriminantAnalysis .

from sklearn.metrics import accuracy_score, log_loss
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC, LinearSVC, NuSVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier, GradientBoostingClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis


classifiers = [
    KNeighborsClassifier(),
    SVC(kernel="rbf", C=0.025, probability=True),
    NuSVC(probability=True),
    DecisionTreeClassifier(),
    RandomForestClassifier(),
    AdaBoostClassifier(),
    GradientBoostingClassifier(),
    GaussianNB(),
    LinearDiscriminantAnalysis()    
    ]



for clf in classifiers:
        
    my_pipeline = Pipeline(steps=[('preprocessor', preprocessor),
                              ('model', clf)
                             ])

    my_pipeline.fit(X_train, y_train)

    name = clf.__class__.__name__
    
    print("="*30)
    print(name)
    
    print('****Results****')
    train_predictions = my_pipeline.predict(X_valid)
    acc = accuracy_score(y_valid, train_predictions)
    print("Accuracy: {:.4%}".format(acc))
    
    train_predictions = my_pipeline.predict_proba(X_valid)
    ll = log_loss(y_valid, train_predictions)
    print("Log Loss: {}".format(ll))
    
        
print("="*30)
==============================
KNeighborsClassifier
****Results****
Accuracy: 74.0741%
Log Loss: 4.71142932321887
==============================
SVC
****Results****
Accuracy: 68.5185%
Log Loss: 0.5079557348761315
==============================
NuSVC
****Results****
Accuracy: 75.9259%
Log Loss: 0.4639978645084237
==============================
DecisionTreeClassifier
****Results****
Accuracy: 68.5185%
Log Loss: 10.873318494694104
==============================
RandomForestClassifier
****Results****
Accuracy: 74.0741%
Log Loss: 0.4456363904734124
==============================
AdaBoostClassifier
****Results****
Accuracy: 79.6296%
Log Loss: 0.5592596234218726
==============================
GradientBoostingClassifier
****Results****
Accuracy: 74.0741%
Log Loss: 0.9540074689883228
==============================
GaussianNB
****Results****
Accuracy: 81.4815%
Log Loss: 0.5448657681139126
==============================
LinearDiscriminantAnalysis
****Results****
Accuracy: 83.3333%
Log Loss: 0.4406757975023656
==============================