PCA e divisione treno / test / convalida

Aug 19 2020

Ho un problema di classificazione binaria con 1149 osservazioni e 13.454 predittori. Voglio applicare la metodologia descritta da cbeleites insoddisfatti di SX in PCA e la divisione treno / test .

In questo contesto, ho due domande:

(i) Se eseguo una ricerca sulla griglia per il numero di PC da utilizzare, non è corretto testare un numero di PC da utilizzare maggiore del numero di osservazioni nel set di test? Mi sembra intuitivo che il numero massimo di PC che dovrebbero essere testati nella griglia di ricerca deve essere uguale o inferiore al numero di osservazioni nel set di test (presumibilmente per evitare una situazione p >> n).

(ii) È più corretto utilizzare un set di hold-out? vale a dire prima utilizzare 10 volte la convalida incrociata per trovare il numero ottimale di PC utilizzando il 90% dei dati come descritto da cbeleiti insoddisfatti di SX , quindi adattare un nuovo stimatore utilizzando il numero ottimale di PC utilizzando tutti i dati che sono stati utilizzati nel primo passo prevedere la probabilità delle classi del set di hold-out?

EDIT Giusto per essere più chiari, il mio codice assomiglia a questo:

tests=[]
pps=[]
pcs=[]
skf=model_selection.StratifiedKFold(n_splits=10,random_state=61,shuffle=True)

for i in (2,5,10,25,50,100,114):

    tmp_pps=[]
    tmp_tests=[]

    for train_index, test_index in skf.split(X, y):
    
        estimator = SVC(probability=True)
        pca = PCA(i, svd_solver='arpack')
        scaler= StandardScaler()
    
        X_train, X_test = X[train_index], X[test_index]
        y_train, y_test = y[train_index], y[test_index]
    
        fScaler = scaler.fit(X_train)
        X_train_scaled = fScaler.transform(X_train)
        X_test_scaled = fScaler.transform(X_test)
    
        fpca = pca.fit(X_train_scaled)
        X_train_PCA = pca.transform(X_train_scaled)
        X_test_PCA = pca.transform(X_test_scaled)
    
        ft = estimator.fit(X_train_PCA, y_train)
        pp = estimator.predict_proba(X_test_PCA)[:, 1]
    
        tmp_tests.append(y_test)
        tmp_pps.append(pp)
    
    tests.append(tmp_tests)
    pps.append(tmp_pps)
    pcs.append(i)

for i in range(len(pcs)):
    pp = np.concatenate(res[i]).ravel()
    y_test = np.concatenate(tests[i]).ravel()
    score = roc_auc_score(y_test, pp)
    print(pcs[i],score)

È un approccio errato / parziale?

Risposte

gunes Aug 19 2020 at 01:30

i) Sì, il numero di PC dovrebbe essere inferiore o uguale al numero di osservazioni perché la matrice dei dati (si assume la media normalizzata senza perdita di generalità), $X_{n\times p}$, ha rango $\leq \min(n,p)=n$, in questo caso. $X^TX$ avrà rango $\leq n$ anche perché $\text{rank}(AB)\leq \text{rank}(A)$.

ii) Dal momento che si dispone di un numero limitato di osservazioni, l'utilizzo della convalida incrociata nella scelta del miglior numero di PC potrebbe essere migliore. È necessario trovare un criterio (ad esempio, coprire la varianza del 95%) e uno schema di voto adeguato per fondere le decisioni provenienti da diverse pieghe. Alla fine, puoi utilizzare tutti i tuoi dati di allenamento per trovare i PC. Il set di test dovrebbe essere separato dall'inizio, cioè non dovresti usarlo nemmeno per selezionare il numero di PC.