<jupyter_start><jupyter_text>Developing an Embedding + CNN Model for Sentiment Analysis* Word embeddings are a technique for representing text where different words with similar meaning have a similar real-valued vector representation.  1. Movie Review Dataset<jupyter_code>from nltk.corpus import stopwords
import string 
import re
from os import listdir
from collections import Counter
from numpy import array
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.utils.vis_utils import plot_model
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Flatten
from keras.layers import Embedding
from keras.layers.convolutional import Conv1D
from keras.layers.convolutional import MaxPooling1D

# load doc into memory
def load_doc(filename):
    # open the file as read only
    file = open(filename,'r')
    # read all text
    text = file.read()
    # close the file
    file.close()
    return text

# turn a doc into clean tokens
def clean_doc(doc,vocab):
    # split into tokens by white space
    tokens = doc.split()
    # prepare regex for char filtering
    re_punc = re.compile('[%s]' % re.escape(string.punctuation))
    # remove punctuation from each word
    tokens = [re_punc.sub('',w) for w in tokens]
    # filter out tokens not in vocab
    tokens = [w for w in tokens if w in vocab]
    tokens = ' '.join(tokens)
    
    return tokens
    

# load all docs in a directory
def process_docs(directory,vocab,is_train):
    documents = list()
    # walk through all files in the folder
    for filename in listdir(directory):
        # skip any reviews in the test set
        if is_train and filename.startswith('cv9'):
            continue
        if not is_train and not filename.startswith('cv9'):
            continue
        # create the full path of the file to open
        path = directory + '/' + filename
        # load the doc
        doc = load_doc(path)
        # clean doc
        tokens = clean_doc(doc,vocab)
        # add to list
        documents.append(tokens)
    return documents
        
# load and clean a dataset
def load_clean_dataset(vocab,is_train):
    # load documents
    neg = process_docs('txt_sentoken/neg',vocab,is_train)
    pos = process_docs('txt_sentoken/pos',vocab,is_train)
    docs = neg + pos
    # prepare labels
    labels = array([0 for _ in range(len(neg))] + [1 for _ in range(len(pos))])
    return docs,labels

# fit a tokenizer
def create_tokenizer(lines):
    tokenizer = Tokenizer()
    tokenizer.fit_on_texts(lines)
    return tokenizer

# integer encode and pad documents
def encode_docs(tokenizer,max_length,docs):
    # integer encode
    encoded = tokenizer.texts_to_sequences(docs)
    # pad sequences
    padded = pad_sequences(encoded,maxlen=max_length,padding='post')
    return padded

# define the model
def define_model(vocab_size,max_length):
    model = Sequential()
    model.add(Embedding(vocab_size,100,input_length=max_length))
    model.add(Conv1D(filters=32,kernel_size=8,activation='relu'))
    model.add(MaxPooling1D(pool_size=2))
    model.add(Flatten())
    model.add(Dense(10,activation='relu'))
    model.add(Dense(1,activation='sigmoid'))
    
    # compile network
    model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])
    
    # summarize defined model
    model.summary()
    plot_model(model,to_file='CNNmodel.png',show_shapes=True)
    return model

# load the vocabulary
vocab_filename = 'vocab.txt'
vocab = load_doc(vocab_filename)
vocab = set(vocab.split())

# load training data
train_docs,ytrain = load_clean_dataset(vocab,True)
# create the tokenizer
tokenizer = create_tokenizer(train_docs)
# define vocabulary size
vocab_size = len(tokenizer.word_index) + 1
print('Vocabulary size: %d' % vocab_size)
# calculate the maximum sequence length
max_length = max([len(s.split()) for s in train_docs])
print('Maximum length: %d' %max_length)
# encode data
Xtrain = encode_docs(tokenizer,max_length,train_docs)
# define model
model = define_model(vocab_size,max_length)
# fit network
model.fit(Xtrain,ytrain,epochs=10,verbose=2)
# save the model
model.save('model.h5')
from keras.models import load_model
# classify a review as negative or positive
def predict_sentiment(review,vocab,tokenizer,max_length,model):
    # clean review
    line = clean_doc(review,vocab)
    # encode and pad review
    padded = encode_docs(tokenizer,max_length,[line])
    # predict sentiment
    yhat = model.predict(padded,verbose=0)
    # retrieve predicted percentage and label
    percent_pos = yhat[0,0]
    if round(percent_pos) != 0:
        return percent_pos, 'POSITIVE'
    return (1-percent_pos), 'NEGATIVE'


# load the vocabulary
vocab_filename = 'vocab.txt'
vocab = load_doc(vocab_filename)
vocab = set(vocab.split())

# load all reviews
train_docs,ytrain = load_clean_dataset(vocab,True)
test_docs,ytest = load_clean_dataset(vocab,False)

# create the tokenizer
tokenizer = create_tokenizer(train_docs)

# define vocabulary size
vocab_size = len(tokenizer.word_index) + 1
print('Vocabulary size: %d' % vocab_size)

# calculate the maximum sequence length
max_length = max([len(s.split()) for s in train_docs])
print('Maximum length: %d' % max_length)

# encode data
Xtrain = encode_docs(tokenizer,max_length,train_docs)
Xtest = encode_docs(tokenizer,max_length,test_docs)

# load the model
model = load_model('model.h5')

# evaluate model on training dataset
_, acc = model.evaluate(Xtrain,ytrain,verbose=0)
print('Train Accuracy: %.2f' %(acc*100))
# evaluate model on test dataset
_, acc = model.evaluate(Xtest,ytest,verbose=0)
print('Test Accuracy: %.2f' %(acc*100))

# test positive text
text = 'Nice Movie!'
percent,sentiment = predict_sentiment(text,vocab,tokenizer,max_length,model)
print('Review: [%s]\nSentiment: %s (%.3f%%)' %(text,sentiment,percent*100))

# test negative text
text = 'This is a bad movie.Do not watch it.It sucks.'
percent,sentiment = predict_sentiment(text,vocab,tokenizer,max_length,model)
print('Review: [%s]\nSentiment: %s (%.3f%%)' %(text,sentiment,percent*100))<jupyter_output>Vocabulary size: 14781
Maximum length: 1244
Train Accuracy: 100.00
Test Accuracy: 86.00
Review: [Nice Movie!]
Sentiment: NEGATIVE (83.869%)
Review: [This is a bad movie.Do not watch it.It sucks.]
Sentiment: NEGATIVE (87.204%)
{'fraction_non_alphanumeric': 0.10174555747759081, 'fraction_numerical': 0.012108822141846201, 'mean_word_length': 4.496974935177183, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '76909', 'license': 'MIT', 'n_tokens_mistral': 2134, 'n_tokens_neox': 2056, 'n_words': 557, 'path': 'Embedding + CNN Model for Sentiment Analysis.ipynb', 'repo_name': 'kuluruvineeth/Deep-Learning-for-NLP', 'size': '6359'}