Dentro de esta clase utilizaremos un modelo de aprendizaje supervisado para predecir el sentimiento. Para ello, supongamos que estamos trabajando con las reseñas de ciertos productos, así como el conjunto de datos con el cual trabajamos sobre reseñas de productos vendidos en amazon. Una tarea de aprendizaje supervisado intentará clasificar cualquier reseña nueva como una positiva o negativa, según la información de las reseñas clasificadas que ya tenemos. De modo que el tipo de problema es de clasificación, donde, dado que tenemos dos etiquetas (positivo y negativo), entonces es un problema de clasificación binaria.
Un algorítmo que se utiliza comúnmente en las tareas de clasificación es una regresión logística
Recordemos que en la regresión lineal, ajustamos una recta para aproximar una relación. En su lugar, en una regresión logística estamos ajustando una curva "s", denominada también función sigmoidea. Otro punto de comparativa es que, en la regresión lineal, estamos prediciendo un resultado numérico continuo, pero con la regresión logística, estimamos la probabilidad de que el resultado pertenezca a la categoría 1 o a la categoría 2. En el caso de nuestro ejemplo, estimaríamos la probabilidad:
$$ P(sentimiento=positivo\ |\ reseña ) \ \ \ \ \ \textrm{y} \ \ \ \ \ P(sentimiento=negativo\ |\ reseña ) $$Dado que estamos estimando una probabilidad y queremos que el resultado estén entre el 0 y el 1, modelamos los valores de $x$ utilizando la función sigmoidea. Por ejemplo, si en una reseña tenemos una probabilidad estimada de 0.7, lo cual redondeamos a 1, podremos decir entonces que el sentimiento es positivo (donde configuramos que el 1 está asociado a que el sentimiento es positivo y que el 0 está asociado con el sentimiento negativo); del mismo modo, si, dada una reseña, tenemos que la probabilidad estimada es de 0.2, que redondea a 0, podremos decir que el sentimiento predicho es de negativo.
Para utiliza la regresión logística en Python, escribimos
# Importacion necesaria
from sklearn.linear_model import LogisticRegression
# Mandamos a llamar a la funcion de regresion logistica
# y creamos un objeto clasificador logistico.
# Ademas, ajustamos el modelo para las variables previamente
# definidas X y y
log_reg = LogisticRegression().fit(X,y)
donde X
corresponde a las características o variables regresoras y y
corresponde a la variable objetivo (que es la etiqueta negativo o positivo), donde en ambas variables éstas son arrays numpy.
Por otro lado, cómo podremos saber si nuestro modelo es bueno. Para ello veremos la diferencia entre el valor real y el valor predicho, donde previamente separamos nuestros datos en un conjunto de entrenamiento y uno de pruebas. Así, si evaluamos nuestro modelo sobre el conjunto de pruebas, podemos comparar los valores predichos con los valores reales, lo cual nos dará un indicio de qué tan bien está funcionando el modelo. Una buena métrica para evaluar un modelo es la precisión (accuracy), la cual se obtiene de considerar la fracción entre las predicciones que el modelo acertó contra el total de predicciones. Así, si la precisión es cercana a uno, tenemos indicios de que nuestro modelo es bueno.
Una manera de calcular la precisión es:
log_reg = LogisticRegression().fic(X,y)
# Precicion/puntuacion
score = log_reg.score(X, y)
print(score)
De manera alternativa
# Importacion necesaria
from sklearn.metrics import accuracy_score
# Requerimos calcular las predicciones
y_pred = log_reg.predict(X)
# Evaluacion del modelo mediante la precision
accuracy = accuracy_score(y, y_pred)
donde dicha función dará un tipo de métrica dependiendo del modelo que se use.
Ahora bien, lo que se hará será dividir los datos en un conjunto de entrenamiento, el cual nos servirá, justamente, para entrenar al modelo; tendremos también un conjunto de pruebas para ver si el modelo entrenado funciona bien en datos nuevos con los cuales no ha trabajado. Para ello escribimos
# Importacion necesaria
from sklearn.model_selection import train_test_split
# train_test_split toma como argumento matrices, listas o dataframes
X_train, y_train, X_test, y_test = train_test_split(X, y,
test_size=0.2,
random_state=123,
stratify=y)
donde stratify nos permite asegurarnos de que el conjunto de entrenamiento y de pruba tengan proporciones similares de ambas muestras. Luego, podemos obtener el valor de precisión del modelo para los datos de entrenamiento y para los datos de prueba. Es claro que la presición para los datos de prueba es menor a la presición para los datos de entrenamiento.
Otra forma de medir y ver el desempeño de un modelo es mediante la matriz de confusión
. | Valor real = 1 | Valor real = 0 |
---|---|---|
Predicción = 1 | Verdadero positivo | Falso positivo |
Predicción = 0 | Falso negativo | Verdadero negativo |
donde:
En Python podemos utilizar la matriz de confusión escribiendo
# Importacion necesaria
from sklearn.metrica import confusion_matrix
# Construccion de la regresion logistica y prediccion de las
# etiquetas en el conjunto de prueba
log_reg = LogisticRegression().fic(X_train, y_train)
y_pred = log_reg.predict(X_train)
# Matriz de confusion
print(confusion_matrix(y_test, y_pred) / len(y_test))
### Ejemplo de salida
[[0.3782 0.1222]
[0.1351 0.3635]]
lo cual nos arrojará proporciones en las celdas de la matriz y donde:
Ahora bien, para poder emplear el modelo de regresión logística usando como características textos, así como las reseñas, deberemos de transformar los campos de texto en columnas numéricas, lo cual nos daría como resultado muchas características, lo cual puede hacer que el modelo sea bastante complejo. Un modelo complejo puede ocurrir en algunos escenarios:
Una forma de evitar los modelos complejos es mediante la regularización, donde estaremos penalizando o restringiendo la función del modelo. Ésta se aplica de manera predeterminada en la función de regresión logística de sklearn.
Implementaremos todo lo anterior para las reseñas de productos de amazon, para ello:
import pandas as pd
data = pd.read_csv('amazon_reviews_sample.csv')[['score', 'review']]
data.head()
score | review | |
---|---|---|
0 | 1 | Stuning even for the non-gamer: This sound tr... |
1 | 1 | The best soundtrack ever to anything.: I'm re... |
2 | 1 | Amazing!: This soundtrack is my favorite musi... |
3 | 1 | Excellent Soundtrack: I truly like this sound... |
4 | 1 | Remember, Pull Your Jaw Off The Floor After H... |
data
score | review | |
---|---|---|
0 | 1 | Stuning even for the non-gamer: This sound tr... |
1 | 1 | The best soundtrack ever to anything.: I'm re... |
2 | 1 | Amazing!: This soundtrack is my favorite musi... |
3 | 1 | Excellent Soundtrack: I truly like this sound... |
4 | 1 | Remember, Pull Your Jaw Off The Floor After H... |
... | ... | ... |
9995 | 1 | A revelation of life in small town America in... |
9996 | 1 | Great biography of a very interesting journal... |
9997 | 0 | Interesting Subject; Poor Presentation: You'd... |
9998 | 0 | Don't buy: The box looked used and it is obvi... |
9999 | 1 | Beautiful Pen and Fast Delivery.: The pen was... |
10000 rows × 2 columns
data.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 10000 entries, 0 to 9999 Data columns (total 2 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 score 10000 non-null int64 1 review 10000 non-null object dtypes: int64(1), object(1) memory usage: 156.4+ KB
Consideraremos un filtrado de datos para las reseñas positivas
data_positive = pd.DataFrame(data[data.score == 1].review)
data_positive
review | |
---|---|
0 | Stuning even for the non-gamer: This sound tr... |
1 | The best soundtrack ever to anything.: I'm re... |
2 | Amazing!: This soundtrack is my favorite musi... |
3 | Excellent Soundtrack: I truly like this sound... |
4 | Remember, Pull Your Jaw Off The Floor After H... |
... | ... |
9990 | Psychological thriller!: This movie really sc... |
9991 | A little more money than what I expected to s... |
9995 | A revelation of life in small town America in... |
9996 | Great biography of a very interesting journal... |
9999 | Beautiful Pen and Fast Delivery.: The pen was... |
4903 rows × 1 columns
# Veamos la primer resegnia
data_positive.iloc[0][0]
' Stuning even for the non-gamer: This sound track was beautiful! It paints the senery in your mind so well I would recomend it even to people who hate vid. game music! I have played the game Chrono Cross but out of all of the games I have ever played it has the best music! It backs away from crude keyboarding and takes a fresher step with grate guitars and soulful orchestras. It would impress anyone who cares to listen! ^_^\r\n'
import re
# Patron de busqueda
# Quitamos los <br> /><br> /> o quitamos todos los caracteres que no son
# alfanumericos o todos los guiones bajos
pattern = re.compile(r'<br /><br />|[^\w]|_')
# Sustituimos todos los <br /><br /> por espacios en blanco
data_positive.review = data_positive.review.apply(lambda x: pattern.sub(' ', x))
# Veamos la primer resegnia
data_positive.iloc[0][0]
' Stuning even for the non gamer This sound track was beautiful It paints the senery in your mind so well I would recomend it even to people who hate vid game music I have played the game Chrono Cross but out of all of the games I have ever played it has the best music It backs away from crude keyboarding and takes a fresher step with grate guitars and soulful orchestras It would impress anyone who cares to listen '
data_positive.iloc[1][0]
' The best soundtrack ever to anything I m reading a lot of reviews saying that this is the best game soundtrack and I figured that I d write a review to disagree a bit This in my opinino is Yasunori Mitsuda s ultimate masterpiece The music is timeless and I m been listening to it for years now and its beauty simply refuses to fade The price tag on this is pretty staggering I must say but if you are going to buy any cd for this much money this is the only one that I feel would be worth every penny '
Convertimos y unimos todas las resegnias positivas en un solo string
positive_reviews = ' '
for i in range(len(data_positive)):
positive_reviews += data_positive.iloc[i][0]
positive_reviews[:1000]
' Stuning even for the non gamer This sound track was beautiful It paints the senery in your mind so well I would recomend it even to people who hate vid game music I have played the game Chrono Cross but out of all of the games I have ever played it has the best music It backs away from crude keyboarding and takes a fresher step with grate guitars and soulful orchestras It would impress anyone who cares to listen The best soundtrack ever to anything I m reading a lot of reviews saying that this is the best game soundtrack and I figured that I d write a review to disagree a bit This in my opinino is Yasunori Mitsuda s ultimate masterpiece The music is timeless and I m been listening to it for years now and its beauty simply refuses to fade The price tag on this is pretty staggering I must say but if you are going to buy any cd for this much money this is the only one that I feel would be worth every penny Amazing This soundtrack is my favorite music of all tim'
len(positive_reviews)
2112327
Luego, quitaremos el exceso de espacios en blanco
# Si aparace un espacio en blanco una o mas veces
pattern = re.compile(r' +')
# lo sustituiremos por solo un espacio en blanco
positive_reviews2 = pattern.sub(' ', positive_reviews)
positive_reviews2[:1000]
' Stuning even for the non gamer This sound track was beautiful It paints the senery in your mind so well I would recomend it even to people who hate vid game music I have played the game Chrono Cross but out of all of the games I have ever played it has the best music It backs away from crude keyboarding and takes a fresher step with grate guitars and soulful orchestras It would impress anyone who cares to listen The best soundtrack ever to anything I m reading a lot of reviews saying that this is the best game soundtrack and I figured that I d write a review to disagree a bit This in my opinino is Yasunori Mitsuda s ultimate masterpiece The music is timeless and I m been listening to it for years now and its beauty simply refuses to fade The price tag on this is pretty staggering I must say but if you are going to buy any cd for this much money this is the only one that I feel would be worth every penny Amazing This soundtrack is my favorite music of all time hands down The intense sa'
len(positive_reviews2)
2044858
# Importacion necesaria
from wordcloud import WordCloud
import matplotlib.pyplot as plt
plt.figure(figsize=(10,6))
# Instanciamos un objeto WordCloud cambiando el color de fondo
# y actuando sobre las resegnias positivas limpias
cloud_positive = WordCloud(background_color='white').generate(positive_reviews2)
# Graficamos
plt.imshow(cloud_positive, interpolation='bilinear')
# Configuramos que los ejes no sean visibles
plt.axis('off')
plt.show()
Notamos varias palabras referentes a las reseñas positivas, notamos que la palabra book es la que más aparece, de modo que la mayoría de las reseñas son de libros. Lo que haremos después será quitar las palabras vacías y añadiremos a éstas las palabras book, song, people, product, video
# Importamos ademas la lista predefinida de palabras vacias
# del ingles de sklearn
from sklearn.feature_extraction.text import ENGLISH_STOP_WORDS
# Podemos enriquecer, o agregar, mas palabras vacias a la lista predefinida
# de las palabras vacias de sklearn, por ejemplo:
stop_words = ENGLISH_STOP_WORDS.union(['book', 'song',' people', 'product',
'video', 'movie', 'read', 'music',
'CD', 'film', 'song', 'DVD',
'album', 'day', 'books', 'time'])
# Instanciamos un objeto WordCloud cambiando el color de fondo
# y actuando sobre las resegnias positivas limpias
cloud_positive = WordCloud(background_color='white',
stopwords=stop_words).generate(positive_reviews2)
# Graficamos
plt.figure(figsize=(10, 6))
plt.imshow(cloud_positive, interpolation='bilinear')
# Configuramos que los ejes no sean visibles
plt.axis('off')
plt.show()
lo cual nos da una mejor perspectiva de las palabras que más aparecen en las reseñas positivas
data_positive.head()
review | |
---|---|
0 | Stuning even for the non gamer This sound tr... |
1 | The best soundtrack ever to anything I m re... |
2 | Amazing This soundtrack is my favorite musi... |
3 | Excellent Soundtrack I truly like this sound... |
4 | Remember Pull Your Jaw Off The Floor After H... |
Después, tokenizaremos cada reseña
# Importacion necesaria
from nltk.corpus.reader.tagged import word_tokenize
# Ejemplo
word_tokenize('hello how are you'.lower())
['hello', 'how', 'are', 'you']
# Tokenizacion
data_positive['tokens'] = data_positive.review.apply(lambda x: word_tokenize(x.lower()))
data_positive.head()
review | tokens | tokens_lemm | |
---|---|---|---|
0 | Stuning even for the non gamer This sound tr... | [stuning, even, for, the, non, gamer, this, so... | [Stuning, even, for, the, non, gamer, This, so... |
1 | The best soundtrack ever to anything I m re... | [the, best, soundtrack, ever, to, anything, i,... | [The, best, soundtrack, ever, to, anything, I,... |
2 | Amazing This soundtrack is my favorite musi... | [amazing, this, soundtrack, is, my, favorite, ... | [Amazing, This, soundtrack, is, my, favorite, ... |
3 | Excellent Soundtrack I truly like this sound... | [excellent, soundtrack, i, truly, like, this, ... | [Excellent, Soundtrack, I, truly, like, this, ... |
4 | Remember Pull Your Jaw Off The Floor After H... | [remember, pull, your, jaw, off, the, floor, a... | [Remember, Pull, Your, Jaw, Off, The, Floor, A... |
Luego, lematizaremos cada token:
# Importacion necesaria
from nltk.stem import WordNetLemmatizer
# Instanciamos
lemattizer = WordNetLemmatizer()
# Crearemos una funcion auxiliar
def lematizar(tokens):
tokens_lemmatizados = []
for token in tokens:
tokens_lemmatizados.append(lemattizer.lemmatize(token))
return tokens_lemmatizados
# Creamos una columna nueva con los tokens lematizados
data_positive['tokens_lemm'] = data_positive.tokens.apply(lambda x: lematizar(x))
data_positive.head()
review | tokens | tokens_lemm | |
---|---|---|---|
0 | Stuning even for the non gamer This sound tr... | [stuning, even, for, the, non, gamer, this, so... | [stuning, even, for, the, non, gamer, this, so... |
1 | The best soundtrack ever to anything I m re... | [the, best, soundtrack, ever, to, anything, i,... | [the, best, soundtrack, ever, to, anything, i,... |
2 | Amazing This soundtrack is my favorite musi... | [amazing, this, soundtrack, is, my, favorite, ... | [amazing, this, soundtrack, is, my, favorite, ... |
3 | Excellent Soundtrack I truly like this sound... | [excellent, soundtrack, i, truly, like, this, ... | [excellent, soundtrack, i, truly, like, this, ... |
4 | Remember Pull Your Jaw Off The Floor After H... | [remember, pull, your, jaw, off, the, floor, a... | [remember, pull, your, jaw, off, the, floor, a... |
y obtenemos la longitud de cada lista de tokens
# Creamos una columna nueva con la longitud de cada lista de tokens
data_positive['long'] = data_positive.tokens.apply(lambda x: len(x))
data_positive.head()
review | tokens | tokens_lemm | long | |
---|---|---|---|---|
0 | Stuning even for the non gamer This sound tr... | [stuning, even, for, the, non, gamer, this, so... | [stuning, even, for, the, non, gamer, this, so... | 80 |
1 | The best soundtrack ever to anything I m re... | [the, best, soundtrack, ever, to, anything, i,... | [the, best, soundtrack, ever, to, anything, i,... | 102 |
2 | Amazing This soundtrack is my favorite musi... | [amazing, this, soundtrack, is, my, favorite, ... | [amazing, this, soundtrack, is, my, favorite, ... | 136 |
3 | Excellent Soundtrack I truly like this sound... | [excellent, soundtrack, i, truly, like, this, ... | [excellent, soundtrack, i, truly, like, this, ... | 122 |
4 | Remember Pull Your Jaw Off The Floor After H... | [remember, pull, your, jaw, off, the, floor, a... | [remember, pull, your, jaw, off, the, floor, a... | 90 |
data_positive.sort_values('long')[['review', 'long']]
review | long | |
---|---|---|
881 | Good read ... | 4 |
8887 | First Knight Cassette Excellent service p... | 15 |
7654 | Question of thought How would Nietzsche crit... | 15 |
7932 | excellent Original fun breathless ... | 15 |
7951 | great subsitute for sony memory stick Great ... | 16 |
... | ... | ... |
2271 | It ll get in your head I saw the video f... | 203 |
6576 | I love it Ray J has soul I love this cd so ... | 205 |
303 | Fun To Listen To This is the second best Ca... | 208 |
4313 | Has Streisand stayed too long at the fair NO... | 208 |
8257 | cabin worthy Live in New Mexico and have a s... | 215 |
4903 rows × 2 columns
import warnings
warnings.filterwarnings('ignore')
from sklearn.feature_extraction.text import TfidfVectorizer
# Construimos el vectorizador configuramos el set de las palabras
# vacias que ya teniamos. Tambien, configuramos la consideracion de
# unigramas y bigramas. Establecemos un maximo de frecuencia
# para las caracteristicas de termino. Y ajustamos sobre todas las
# resegnias
vect = TfidfVectorizer(stop_words=stop_words, ngram_range=(1,2),
max_features=200).fit(data.review)
# Creamos la matriz dispersa
X = vect.transform(data.review)
# Creamos un dataframe
reviews_transformed = pd.DataFrame(X.toarray(), columns=vect.get_feature_names())
reviews_transformed.head()
10 | able | acting | action | actually | ago | amazing | amazon | author | away | ... | work | works | world | worst | worth | writing | written | wrong | year | years | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | 0.296352 | ... | 0.000000 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 |
1 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | 0.000000 | ... | 0.000000 | 0.0 | 0.0 | 0.0 | 0.224690 | 0.0 | 0.0 | 0.0 | 0.0 | 0.213913 |
2 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.432583 | 0.0 | 0.0 | 0.000000 | ... | 0.161535 | 0.0 | 0.0 | 0.0 | 0.180921 | 0.0 | 0.0 | 0.0 | 0.0 | 0.172243 |
3 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | 0.000000 | ... | 0.000000 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 |
4 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | 0.000000 | ... | 0.000000 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 |
5 rows × 200 columns
score
del dataframe original.Notemos que los siguientes dataframes tienen el mismo número de filas
reviews_transformed.shape
(10000, 200)
data.shape
(10000, 2)
Esto es, las filas de las reseñas son respetadas, así, hacemos la asignación del score como sigue
data.score
0 1 1 1 2 1 3 1 4 1 .. 9995 1 9996 1 9997 0 9998 0 9999 1 Name: score, Length: 10000, dtype: int64
reviews_transformed['score'] = data.score
reviews_transformed.head()
10 | able | acting | action | actually | ago | amazing | amazon | author | away | ... | works | world | worst | worth | writing | written | wrong | year | years | score | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | 0.296352 | ... | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 1 |
1 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | 0.000000 | ... | 0.0 | 0.0 | 0.0 | 0.224690 | 0.0 | 0.0 | 0.0 | 0.0 | 0.213913 | 1 |
2 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.432583 | 0.0 | 0.0 | 0.000000 | ... | 0.0 | 0.0 | 0.0 | 0.180921 | 0.0 | 0.0 | 0.0 | 0.0 | 0.172243 | 1 |
3 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | 0.000000 | ... | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 1 |
4 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | 0.000000 | ... | 0.0 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.0 | 0.000000 | 1 |
5 rows × 201 columns
Continuando
# Importacion necesaria
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix
from sklearn.linear_model import LogisticRegression
# Definimos las variables en cuestion
y = np.array(reviews_transformed.score).reshape(-1, 1)
X = np.array(reviews_transformed.drop('score', axis=1))
# Hacemos la division de los datos
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.2, random_state=123)
# Entrenamos un modelo de regresion logistica
log_reg = LogisticRegression().fit(X_train, y_train)
# Realizamos la prediccion de las etiquetas
y_pred = log_reg.predict(X_test)
# Imprimimos la puntuacion de precision y la matriz de confusion
print('Precisión del modelo en el conjunto de prueba: ', accuracy_score(y_test, y_pred))
print()
print(confusion_matrix(y_test, y_pred) / len(y_test))
Precisión del modelo en el conjunto de prueba: 0.794 [[0.414 0.1005] [0.1055 0.38 ]]
Probemos nuestro clasificador, para lo cual:
# Resegnia nueva
res = 'The book of Don Quixote is a spectacular, beautiful and sublime work of Cervantes'
# Creamos la matriz dispersa con el vocabulario y los valores asociados
# ya almacenados de nuestro modelo, referente a la nueva resegnia
X = vect.transform([res])
# Creamos un dataframe para ver la matriz dispersa
reviews_transformed_new = pd.DataFrame(X.toarray(), columns=vect.get_feature_names())
reviews_transformed_new.head()
10 | able | acting | action | actually | ago | amazing | amazon | author | away | ... | work | works | world | worst | worth | writing | written | wrong | year | years | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.526808 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
1 rows × 200 columns
# Realizamos la prediccion del sentiminto
log_reg.predict(reviews_transformed_new)
array([1], dtype=int64)
Por lo que se ha predicho que el sentimiento de la nueva reseña es positivo.