Tecniche di apprendimento automatico per stimare l'età degli utenti in base ai siti di Facebook che preferiscono


25

Ho un database dalla mia applicazione Facebook e sto cercando di utilizzare l'apprendimento automatico per stimare l'età degli utenti in base ai siti Facebook che preferiscono.

Ci sono tre caratteristiche cruciali del mio database:

  • la distribuzione dell'età nel mio set di formazione (in totale 12k di utenti) è distorta rispetto agli utenti più giovani (ovvero ho 1157 utenti di 27 anni e 23 utenti di 65 anni);

  • molti siti non hanno più di 5 liker (ho filtrato i siti FB con meno di 5 liker).

  • ci sono molte più funzioni rispetto ai campioni.

Quindi, le mie domande sono: quale strategia suggeriresti per preparare i dati per ulteriori analisi? Dovrei eseguire una sorta di riduzione della dimensionalità? Quale metodo ML sarebbe più appropriato usare in questo caso?

Uso principalmente Python, quindi i suggerimenti specifici per Python sarebbero molto apprezzati.


1
Quando dici "molte più funzioni rispetto ai campioni", suppongo che intendi che il numero univoco di siti piaciuti sia >> num utenti. È anche il caso del dominio principale dei siti? cioè sono un numero di URL youtube.com o cnn.com nei siti o sono già derivati ​​dal dominio? Mi sto orientando verso la riduzione della dimensionalità comprimendo gli URL nelle radici del dominio piuttosto che nelle pagine specifiche, se possibile.
cwharland,

Grazie per la risposta. Il numero di funzionalità (siti univoci apprezzati) è 32k, mentre il numero di campioni (utenti) è 12k. Le funzionalità sono pagine di Facebook, quindi non è necessario bloccare gli URL. A un utente potrebbe piacere o meno facebook.com/cnn. Mi piace l'idea di provare a stimare l'età degli utenti in base ai link che condividono, però :)
Wojciech Walczak,

Ahhh, ho letto male la descrizione dei siti piaciuti. Grazie per il chiarimento.
cwharland,

Risposte:


16

Una cosa per cominciare sarebbe k-NN. L'idea qui è che hai una matrice utente / articolo e per alcuni degli utenti hai un'età segnalata. L'età per una persona nella matrice dell'oggetto utente potrebbe essere ben determinata da qualcosa come l'età media o media di alcuni vicini più vicini nello spazio degli oggetti.

Quindi ogni utente viene espresso come vettore nello spazio oggetti, trova i k vicini più vicini e assegna al vettore in questione alcune statistiche riassuntive delle età vicine più vicine. Puoi scegliere k su un taglio di distanza o più realisticamente assegnando in modo iterativo le età a un treno che tiene duro e scegliendo k che minimizza l'errore in quel compito.

Se la dimensionalità è un problema, è possibile eseguire facilmente la riduzione in questa configurazione mediante decomposizione a valore singolo scegliendo i vettori che acquisiscono la maggiore varianza nel gruppo.

In tutti i casi, poiché ogni caratteristica è binaria, sembra che la somiglianza del coseno sia la tua metrica sulla distanza.

Devo pensare un po 'di più ad altri approcci (regressione, rf, ecc ...) dato lo stretto focus del tuo spazio delle caratteristiche (tutte le varianti della stessa azione, gradimento) Penso che l'approccio utente / oggetto potrebbe essere il migliore.

Una nota di cautela, se le età che hai per il treno sono auto-segnalate, potresti aver bisogno di correggerne alcune. Le persone su Facebook tendono a segnalare l'età nel decennio in cui sono nate. Traccia un istogramma delle date di nascita (derivate da epoche) e vedi se hai picchi in decenni come anni '70, '80, '90.


Ciao, la tua risposta è abbastanza simile alla mia vera strategia. Ho usato sklearn.neighbors.KNeighborsRegressorcon la metrica del coseno nello spazio ridotto di SVD (dopo aver applicato SVD l'errore di stima medio è sceso da ~ 6 anni a ~ 4). Gli utenti nel mio database hanno un'età compresa tra 18 e 65 anni (gli utenti più anziani sono stati esclusi), quindi ci sono 48 classi possibili. Mi chiedo se non ci siano troppe classi per kNN e se dovrei trattarlo come una regressione o un problema di classificazione (penso che entrambi siano applicabili).
Wojciech Walczak,

Posso dire, aneddoticamente, che ho usato per classe Random Forests per adattarsi a un numero di classi individualmente, quindi ho combinato i risultati di ciascuno di quei modelli in vari modi. In questo caso potresti anche pensare di assegnare le probabilità precedenti all'età di ciascun utente con il kNN, quindi eseguire ogni modello basato su classe, utilizzare quei punteggi per aggiornare le probabilità precedenti per ogni classe e scegliere la classe più probabile tra quelle posteriori. Sembra complicare un po ', ma nel peggiore dei casi avresti la precisione kNN.
cwharland,

7

Di recente ho realizzato un progetto simile in Python (predicendo opinioni usando dati simili a FB) e ho ottenuto buoni risultati con il seguente processo di base:

  1. Leggi nel set di addestramento (n = N) ripetendo riga per riga delimitati da virgole come record e usa un contatore per identificare le pagine più popolari
  2. Per ciascuna delle pagine K più popolari (ne ho usate circa 5000, ma puoi giocare con valori diversi), usa pandas.DataFrame.isin per verificare se a ciascun individuo nel set di training piacciono le pagine, quindi crea un frame di dati N x K dei risultati (lo chiamerò xdata_train)
  3. Crea una serie (la chiamerò ydata_train) contenente tutte le variabili di risultato (nel mio caso opinioni, nella tua età) con lo stesso indice di xdata_train
  4. Imposta un classificatore di foreste casuale tramite scikit-learn per prevedere ydata_train in base a xdata_train
  5. Utilizza i test di convalida incrociata di scikit-learn per modificare i parametri e perfezionare la precisione (ottimizzazione del numero di pagine popolari, numero di alberi, dimensione minima delle foglie, ecc.)
  6. Output classificatore di foresta casuale ed elenco delle pagine più popolari con pickle (o tienilo in memoria se stai facendo tutto in una volta)
  7. Carica il resto dei tuoi dati, carica l'elenco di pagine popolari (se necessario) e ripeti il ​​passaggio 2 per produrre xdata_new
  8. Caricare il classificatore di foresta casuale (se necessario) e utilizzarlo per prevedere i valori per i dati xdata_new
  9. Invia i punteggi previsti a un nuovo CSV o altro formato di output di tua scelta

Nel tuo caso, dovresti scambiare il classificatore con un regressore (quindi vedi qui: http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestRegressor.html ) ma altrimenti lo stesso processo dovrebbe funzionare senza troppi problemi.

Inoltre, dovresti essere consapevole della caratteristica più sorprendente delle foreste casuali in Python: parallelizzazione istantanea! Quelli di noi che hanno iniziato a farlo in R e poi si sono spostati sono sempre sorpresi, soprattutto quando si arriva a lavorare su una macchina con poche decine di core (vedere qui: http://blog.yhathq.com/posts/comparing- random-forest-in-python-and-r.html ).

Infine, nota che questa sarebbe un'applicazione perfetta per l'analisi della rete se disponi dei dati sugli amici e sulle persone stesse. Se riesci ad analizzare l'età degli amici di un utente, l'età dell'utente sarà quasi sicuramente entro un anno o due dalla mediana tra i suoi amici, in particolare se gli utenti sono abbastanza giovani da aver costruito le loro reti di amici mentre sono ancora in scuola (dal momento che la maggior parte saranno compagni di classe). Tale previsione avrebbe probabilmente la meglio su ciò che otterresti dalla modellazione: questo è un esempio da manuale di un problema in cui i dati giusti> il modello giusto ogni volta.

In bocca al lupo!


2
Un aspetto interessante dell'utilizzo dei primi 5000 siti è il fatto che potrebbero non essere bravi a segmentare gli utenti in base all'età. I siti migliori, per costruzione, sono quelli visitati da tutti. Pertanto non sono molto bravi a segmentare i tuoi utenti poiché tutte le possibili classificazioni (età) si sono impegnate con quei siti. Questa è una nozione simile alla parte idf di tf-idf. idf aiuta a filtrare il rumore "tutti hanno questa funzione". In che modo i siti più visitati si classificano come caratteristiche nei grafici a importanza variabile con la RF?
cwharland,

1
Buon punto. Una soluzione semplice per questo sarebbe quella di stratificare il set di dati di allenamento in bin di età J (ad es. 13-16, 17-20, 21-24, ecc.) E prendere le prime pagine (K / J) per ciascun gruppo. Ciò garantirebbe una rappresentazione significativa per ciascun gruppo. Ci saranno sicuramente delle sovrapposizioni tra i gruppi, quindi se tu fossi davvero esigente potresti voler prendere le prime (K / J) pagine uniche per ciascun gruppo, ma penso che potrebbe essere eccessivo.
Therriault,

5

Un altro suggerimento è testare la regressione logistica . Come bonus aggiuntivo, i pesi (coefficienti) del modello ti daranno un'idea di quali siti sono soggetti a limiti di età.

Sklearn offre il pacchetto sklearn.linear_model.LogisticRegression progettato anche per gestire dati sparsi.

Come menzionato nei commenti, nel presente caso, con più variabili di input rispetto ai campioni, è necessario regolarizzare il modello (con sklearn.linear_model.LogisticRegression utilizzare l' penalty='l1'argomento).


1
Con LR dovresti creare più modelli per i cassonetti dell'età, credo. Come confronterebbero due modelli per differenti fasce di età che prevedono la stessa probabilità di inclusione per un utente?
cwharland,

1
Si noti che LR fallisce quando ci sono più variabili delle osservazioni e si comporta male se i presupposti del modello non sono soddisfatti. Per usarlo, la riduzione della dimensionalità deve essere un primo passo.
Christopher Louden,

1
@cwharland non dovresti considerare la variabile di risposta categorica in quanto è continua per natura e discretizzata dalla definizione del problema. Considerarlo categorico significherebbe dire all'algoritmo che la previsione dell'età di 16 anni quando in realtà è 17 è un errore grave come la previsione di 30 quando in realtà è 17. Considerarlo continuo assicura che piccoli errori (16 vs 17) siano considerati piccoli e grandi errori ( 30 vs 17) sono considerati grandi. La regressione logistica viene utilizzata in questo caso per prevedere il valore continuo e non stimare le probabilità posteriori.
damienfrancois,

@ChristopherLouden Hai ragione sul fatto che la versione vaniglia della regressione logistica non è adatta al caso 'large p small n', avrei dovuto menzionare che la regolarizzazione è importante nel presente caso. Aggiorno la mia risposta. Ma LR regolarizzato L1 è una sorta di selezione delle caratteristiche, quindi non considero un passaggio preliminare di FS.
damienfrancois,

@damienfrancois: sono assolutamente d'accordo. Sono solo un po 'preoccupato che in questo caso LR penalizzi troppo duramente i valori intermedi. Non sembra esserci alcuna motivazione per mappare una curva simile a quella sigmoidale dato che non sei particolarmente interessato ai valori estremi dell'età. Forse sto fraintendendo l'uso però.
cwharland,

4

Alcune ricerche di D. Nguyen et al. prova a prevedere l'età dell'utente di Twitter in base ai suoi tweet. Forse li trovi utili. Usano la regressione logistica e lineare.


3

Oltre ai metodi più fantasiosi potresti provare la formula di Bayes

P (I | p1 ... pn) = P (p1 ... pn | I) P (I) / sum_i (P (p1 ... pn | i) P (i))

P (I | p1 ... pn) è la probabilità che un utente appartenga alla fascia di età I se gli piaceva p1, .., pn

P (i) è la probabilità che un utente appartenga alla fascia di età i

P (p1 .. pn | i) è la probabilità che a un utente piaccia p1, .., pn se appartiene alla fascia di età i.

  • Hai già le stime per P (i) dai tuoi dati: questa è solo la proporzione di utenti nella fascia d'età I.
  • Per stimare P (p1 ... pn | i), per ogni fascia d'età stimo la probabilità (frequenza) p_ij come una pagina j. Per avere p_ij diverso da zero per tutto j, è possibile mescolare la frequenza per l'intera popolazione con un peso ridotto.

  • Quindi registra P (p1 ... pn | i) = sum (registra p_ij, i = p1, .., pn), la somma su tutte le pagine che piacciono a un nuovo utente. Questa formula sarebbe approssimativamente vera supponendo che a un utente piacciano le pagine della sua fascia d'età in modo indipendente.

  • Teoricamente, dovresti anche aggiungere log (1-p_ij) per tutto ciò che non gli è piaciuto, ma in pratica dovresti scoprire che la somma di log (1-p_ij) sarà irrilevantemente piccola, quindi non ne avrai bisogno molta memoria.

Se tu o qualcun altro hai provato questo, ti preghiamo di commentare il risultato.


2

Questo è un problema molto interessante

Ne ho affrontato uno analogo analizzando le immagini caricate dagli utenti sul social network. Ho seguito il seguente approccio:

  • Piuttosto che associare i dati alle età (15 anni, 27 anni, ...) quello che ho fatto è stato quello di stabilire diversi gruppi di età: meno di 18, da 18 a 30 e maggiori di 30 (questo è dovuto al problema specifico che eravamo di fronte, ma puoi scegliere gli intervalli che desideri). Questa divisione aiuta molto a risolvere il problema.
  • Successivamente, ho creato un cluster gerarchico (divisivo o aggregativo). Quindi ho scelto quei rami in cui avevo utenti con età note (o età di gruppo) e poi per quel ramo ho esteso la stessa età a quel gruppo.

Questo approccio è un apprendimento semi-supervisionato e l'ho raccomandato nel caso in cui tu abbia solo alcuni dati etichettati.

Si prega di notare che su un social network, le persone di solito mentono sull'età (solo per divertimento o a volte perché vogliono mimetizzarsi sulla rete sociale).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.