python - ensemble - stacking classifier sklearn
Combinando bolsa de palabras y otras características en un modelo usando sklearn y pandas (1)
Estoy tratando de modelar la puntuación que recibe una publicación, según el texto de la publicación y otras características (hora del día, duración de la publicación, etc.)
Me pregunto cómo combinar mejor estos diferentes tipos de características en un modelo. En este momento, tengo algo como lo siguiente (robado here y 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)
Parece muy tonto extraer todas las características que quiero del marco de datos de los pandas, solo para volver a unirlas todas. ¿Hay una mejor manera de hacer este paso?
El CSV se parece a lo siguiente:
ID,message,feature_1,feature_2
1,''This is the text'',4,7
2,''This is more text'',3,2
...
Podrías hacer todo con tu mapa y lambda:
tokenized=map(lambda msg, ft1, ft2: features([msg,ft1,ft2]), posts.message,posts.feature_1, posts.feature_2)
Esto ahorra haciendo su paso temporal provisional e itera a través de las 3 columnas.
Otra solución sería convertir los mensajes en su matriz dispersa de CountVectorizer y unir esta matriz con los valores de características del marco de datos de las publicaciones (esto omite tener que construir un dict y produce una matriz dispersa similar a la que obtendría 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]])
Además, sklearn-pandas tiene DataFrameMapper que también hace lo que estás buscando:
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 no es escasa cuando se usa este último método.
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'']