<jupyter_start><jupyter_text>Sentiment Analysis Using RNN We use an Sequential LSTM to create a supervised learning approach for predicting the sentiment of an article. This notebook was adapted from https://www.kaggle.com/ngyptr/lstm-sentiment-analysis-keras.    Data and Packages Importing<jupyter_code>import numpy as np
import pandas as pd

from sklearn.feature_extraction.text import CountVectorizer
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
from keras.layers import Dense, Embedding, LSTM, SpatialDropout1D
from sklearn.model_selection import train_test_split
from keras.utils.np_utils import to_categorical
import re
df1 = pd.read_csv("./Sentiment Training Data/Classified Articles.csv")
data = pd.read_csv("./Sentiment Training Data/Articles Reading Assignment.csv")
data.head()
data.dropna()
data["Sentiment"] += 1
data["Sentiment"] /= 2

data["Content"] = ["" for i in range(len(data))]
data["Content Length"] = [0 for i in range(len(data))]

for i, row in data.iterrows():
    x = row["URL"]
    
    key_words = df1[df1["source_url"] == x][:1]["contents"].values[0]
    data.at[i, "Content"] = str(key_words)
    data.at[i, "Content Length"] = len(key_words)
    
data.head()<jupyter_output><empty_output><jupyter_text>Word Vector Tokenization<jupyter_code>for idx,row in data.iterrows():
    row[0] = row[0].replace('rt',' ')
    
max_features = 2000
tokenizer = Tokenizer(num_words=max_features, split=' ')
tokenizer.fit_on_texts(data['Content'].values)
X = tokenizer.texts_to_sequences(data['Content'].values)
X = pad_sequences(X, maxlen = max_features)<jupyter_output><empty_output><jupyter_text>Building the LSTM Model<jupyter_code>embed_dim = 128
lstm_out = 196

model = Sequential()
model.add(Embedding(max_features, embed_dim,input_length = X.shape[1]))
model.add(SpatialDropout1D(0.4))
model.add(LSTM(lstm_out, dropout=0.5, recurrent_dropout=0.5))
model.add(Dense(2,activation='softmax'))
model.compile(loss = 'categorical_crossentropy', optimizer='adam',metrics = ['accuracy'])
print(model.summary())<jupyter_output>_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_1 (Embedding)      (None, 2000, 128)         256000    
_________________________________________________________________
spatial_dropout1d_1 (Spatial (None, 2000, 128)         0         
_________________________________________________________________
lstm_1 (LSTM)                (None, 196)               254800    
_________________________________________________________________
dense_1 (Dense)              (None, 2)                 394       
=================================================================
Total params: 511,194
Trainable params: 511,194
Non-trainable params: 0
_________________________________________________________________
None<jupyter_text>Building a Training and Test Set<jupyter_code>Y_dummies = []


for y in data["Sentiment"]:
    if y > 0.5:
        Y_dummies.append([y, (1-y)])
    else:
        Y_dummies.append([(1-y), y])

Y_dummies = np.matrix(Y_dummies)

X_train, X_test, Y_train, Y_test = train_test_split(X,Y_dummies, test_size = 0.5, random_state = 42)
print(X_train.shape,Y_train.shape)
print(X_test.shape,Y_test.shape)<jupyter_output>(125, 2000) (125, 2)
(125, 2000) (125, 2)<jupyter_text>Training the RNN<jupyter_code>batch_size = 32
epochs = 7


model.fit(X_train, Y_train, epochs = epochs, batch_size=batch_size, verbose = 1)<jupyter_output>Epoch 1/7
125/125 [==============================] - 15s 117ms/step - loss: nan - acc: 0.8240
Epoch 2/7
125/125 [==============================] - 13s 103ms/step - loss: nan - acc: 1.0000
Epoch 3/7
125/125 [==============================] - 14s 109ms/step - loss: nan - acc: 1.0000
Epoch 4/7
125/125 [==============================] - 13s 106ms/step - loss: nan - acc: 1.0000
Epoch 5/7
125/125 [==============================] - 13s 108ms/step - loss: nan - acc: 1.0000
Epoch 6/7
125/125 [==============================] - 14s 115ms/step - loss: nan - acc: 1.0000
Epoch 7/7
125/125 [==============================] - 15s 120ms/step - loss: nan - acc: 1.0000<jupyter_text>Evaluating the Model<jupyter_code>score,acc = model.evaluate(X_test, Y_test, verbose = 1, batch_size = batch_size)
print("score: %.2f" % (score))
print("acc: %.2f" % (acc))<jupyter_output>125/125 [==============================] - 3s 23ms/step
score: nan
acc: 1.00<jupyter_text>Assign SentimentsGiven that the RNN produces a probability of the sentiment of an article, we attempt to normalize the value and create binary assignments before exporting it for the time-series analysis process.<jupyter_code>output_data = df1
output_data = output_data.drop("marks",axis=1)

    
tokenizer = Tokenizer(num_words=max_features, split=' ')
tokenizer.fit_on_texts(output_data['c'].values)
X = tokenizer.texts_to_sequences(output_data['c'].values)
X = pad_sequences(X, maxlen = max_features)

predictions = model.predict(X, batch_size=batch_size, verbose=1, steps=None)

predictions_assigned = []

for i in predictions:
    if i[0] > i[1]:
        predictions_assigned.append(0)
    else:
        predictions_assigned.append(1)

output_data["marks"] = predictions_assigned

output_data.to_csv("Articles with Sentiment.csv")

success_count = 0
total_count = 0
for i, row in df1.iterrows():
    elais_sentiment = row["marks"]
    predicted_sentiment = predictions_assigned[i]
    
    if elais_sentiment == predicted_sentiment:
        success_count += 1
    
    total_count += 1
    
    
print("The accuracy on the manually labelled data set is {}".format(float(success_count/total_count)))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.17342729460295633, 'fraction_numerical': 0.04623581986937092, 'mean_word_length': 5.1446673706441395, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 27, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '548401', 'license': 'MIT', 'n_tokens_mistral': 2091, 'n_tokens_neox': 1841, 'n_words': 422, 'path': 'past-team-code/Fall2018Team2/Sentiment Analysis/LSTM Sentiment Analysis - Self Labelled Data.ipynb', 'repo_name': 'shun-lin/project-paradigm-chatbot', 'size': '5818'}