2015-06-04 16 views
15

Sto provando a modellare la partitura ricevuta da un post, in base al testo del post e ad altre caratteristiche (ora del giorno, lunghezza del post, ecc.)Combinazione di parole e altre caratteristiche in un modello utilizzando sklearn e panda

Mi chiedo come combinare al meglio questi diversi tipi di funzionalità in un unico modello. In questo momento, ho qualcosa di simile al seguente (rubato da here e here).

import pandas as pd 
... 

def features(p): 
    terms = vectorizer(p[0]) 
    d = {'feature_1': p[1], 'feature_2': p[2]} 
    for t in terms: 
     d[t] = d.get(t, 0) + 1 
    return d 

posts = pd.read_csv('path/to/csv') 

# Create vectorizer for function to use 
vectorizer = CountVectorizer(binary=True, ngram_range=(1, 2)).build_tokenizer() 
y = posts["score"].values.astype(np.float32) 
vect = DictVectorizer() 

# This is the part I want to fix 
temp = zip(list(posts.message), list(posts.feature_1), list(posts.feature_2)) 
tokenized = map(lambda x: features(x), temp) 
X = vect.fit_transform(tokenized) 

sembra molto stupido per estrarre tutte le caratteristiche che voglio fuori dalla dataframe panda, solo per zip tutti di nuovo insieme. C'è un modo migliore per fare questo passo?

Il CSV sembra qualcosa di simile al seguente:

ID,message,feature_1,feature_2 
1,'This is the text',4,7 
2,'This is more text',3,2 
... 
+0

Puoi mostrare un campione del tuo csv? – elyase

+0

@elyase, ho appena aggiunto una versione giocattolo di esso. – Jeremy

risposta

14

Si potrebbe fare tutto con la mappa e lambda:

tokenized=map(lambda msg, ft1, ft2: features([msg,ft1,ft2]), posts.message,posts.feature_1, posts.feature_2) 

Ciò consente di risparmiare facendo il vostro passo temperatura intermedia e itera attraverso le 3 colonne.

Un'altra soluzione sarebbe convertire i messaggi nella matrice sparsa di CountVectorizer e unirsi a questa matrice con i valori delle caratteristiche del dataframe dei post (questo salta dovendo costruire un dict e produce una matrice sparsa simile a quella che si otterrebbe con DictVectorizer) :

import scipy as sp 
posts = pd.read_csv('post.csv') 

# Create vectorizer for function to use 
vectorizer = CountVectorizer(binary=True, ngram_range=(1, 2)) 
y = posts["score"].values.astype(np.float32) 

X = sp.sparse.hstack((vectorizer.fit_transform(posts.message),posts[['feature_1','feature_2']].values),format='csr') 
X_columns=vectorizer.get_feature_names()+posts[['feature_1','feature_2']].columns.tolist() 


posts 
Out[38]: 
    ID    message feature_1 feature_2 score 
0 1 'This is the text'   4   7  10 
1 2 'This is more text'   3   2  9 
2 3 'More random text'   3   2  9 

X_columns 
Out[39]: 
[u'is', 
u'is more', 
u'is the', 
u'more', 
u'more random', 
u'more text', 
u'random', 
u'random text', 
u'text', 
u'the', 
u'the text', 
u'this', 
u'this is', 
'feature_1', 
'feature_2'] 

X.toarray() 
Out[40]: 
array([[1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 4, 7], 
     [1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 3, 2], 
     [0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 3, 2]]) 

Inoltre sklearn-panda ha DataFrameMapper che fa quello che stai cercando per troppo:

from sklearn_pandas import DataFrameMapper 
mapper = DataFrameMapper([ 
    (['feature_1', 'feature_2'], None), 
    ('message',CountVectorizer(binary=True, ngram_range=(1, 2))) 
]) 
X=mapper.fit_transform(posts) 

X 
Out[71]: 
array([[4, 7, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1], 
     [3, 2, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1], 
     [3, 2, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0]]) 

Nota: X non è scarsa quando si utilizza quest'ultimo metodo.

X_columns=mapper.features[0][0]+mapper.features[1][1].get_feature_names() 

X_columns 
Out[76]: 
['feature_1', 
'feature_2', 
u'is', 
u'is more', 
u'is the', 
u'more', 
u'more random', 
u'more text', 
u'random', 
u'random text', 
u'text', 
u'the', 
u'the text', 
u'this', 
u'this is'] 
+0

grazie a @khammel ho messo questo in un succo https://gist.github.com/danemacaulay/c8e3194b63570de1cf88f431ade32107 –

Problemi correlati