Spaces:
Sleeping
Sleeping
Commit
·
51649e7
1
Parent(s):
a82bbda
Upload 3 files
Browse files- gru_movie_model.h5 +3 -0
- gru_movie_model.ipynb +398 -0
- tokenizer_movie_gru.pickle +3 -0
gru_movie_model.h5
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:2b0fa91a9f80f4388c147f3b4a638fbbb30a6f99834dec25060420fde323afac
|
3 |
+
size 43126776
|
gru_movie_model.ipynb
ADDED
@@ -0,0 +1,398 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "markdown",
|
5 |
+
"metadata": {},
|
6 |
+
"source": [
|
7 |
+
"#### Movie sentiment model - GRU"
|
8 |
+
]
|
9 |
+
},
|
10 |
+
{
|
11 |
+
"cell_type": "code",
|
12 |
+
"execution_count": 1,
|
13 |
+
"metadata": {},
|
14 |
+
"outputs": [],
|
15 |
+
"source": [
|
16 |
+
"import pandas as pd\n",
|
17 |
+
"import matplotlib.pyplot as plt\n",
|
18 |
+
"import seaborn as sns\n",
|
19 |
+
"from numpy import asarray\n",
|
20 |
+
"from numpy import zeros\n",
|
21 |
+
"import tensorflow as tf\n",
|
22 |
+
"from sklearn.model_selection import train_test_split\n",
|
23 |
+
"from sklearn.metrics import classification_report, confusion_matrix, accuracy_score\n",
|
24 |
+
"import pickle"
|
25 |
+
]
|
26 |
+
},
|
27 |
+
{
|
28 |
+
"cell_type": "code",
|
29 |
+
"execution_count": 2,
|
30 |
+
"metadata": {},
|
31 |
+
"outputs": [],
|
32 |
+
"source": [
|
33 |
+
"def getGloveEmbeddings(glovefolderpath):\n",
|
34 |
+
" print(\"---------------------- Getting Glove Embeddings -------------------------\\n\")\n",
|
35 |
+
" embeddings_dictionary = dict()\n",
|
36 |
+
" glove_file = open(f\"{glovefolderpath}\", encoding=\"utf8\")\n",
|
37 |
+
" for line in glove_file:\n",
|
38 |
+
" records = line.split()\n",
|
39 |
+
" word = records[0]\n",
|
40 |
+
" vector_dimensions = asarray(records[1:], dtype='float32')\n",
|
41 |
+
" embeddings_dictionary [word] = vector_dimensions\n",
|
42 |
+
" glove_file.close()\n",
|
43 |
+
" print(\"---------------------- -------------------------\\n\")\n",
|
44 |
+
" return embeddings_dictionary\n",
|
45 |
+
"\n",
|
46 |
+
"\n",
|
47 |
+
"glove_folder=r'D:/STUDY/Sem3/deeplearning/glove.6B/glove.6B.100d.txt'"
|
48 |
+
]
|
49 |
+
},
|
50 |
+
{
|
51 |
+
"cell_type": "code",
|
52 |
+
"execution_count": 3,
|
53 |
+
"metadata": {},
|
54 |
+
"outputs": [],
|
55 |
+
"source": [
|
56 |
+
"maxlen = 100"
|
57 |
+
]
|
58 |
+
},
|
59 |
+
{
|
60 |
+
"cell_type": "code",
|
61 |
+
"execution_count": 4,
|
62 |
+
"metadata": {},
|
63 |
+
"outputs": [],
|
64 |
+
"source": [
|
65 |
+
"dataset = pd.read_csv('movie_data.csv')\n",
|
66 |
+
"\n",
|
67 |
+
"X = dataset['review'].values\n",
|
68 |
+
"y = dataset['sentiment'].values"
|
69 |
+
]
|
70 |
+
},
|
71 |
+
{
|
72 |
+
"cell_type": "code",
|
73 |
+
"execution_count": 5,
|
74 |
+
"metadata": {},
|
75 |
+
"outputs": [],
|
76 |
+
"source": [
|
77 |
+
"X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)"
|
78 |
+
]
|
79 |
+
},
|
80 |
+
{
|
81 |
+
"cell_type": "code",
|
82 |
+
"execution_count": 6,
|
83 |
+
"metadata": {},
|
84 |
+
"outputs": [],
|
85 |
+
"source": [
|
86 |
+
"tokeniser = tf.keras.preprocessing.text.Tokenizer()\n",
|
87 |
+
"tokeniser.fit_on_texts(X_train)\n",
|
88 |
+
"\n",
|
89 |
+
"\n",
|
90 |
+
"# Save the tokenizer using pickle\n",
|
91 |
+
"with open('tokenizer_movie_gru.pickle', 'wb') as handle:\n",
|
92 |
+
" pickle.dump(tokeniser, handle, protocol=pickle.HIGHEST_PROTOCOL)\n",
|
93 |
+
"\n",
|
94 |
+
"\n",
|
95 |
+
"X_train = tokeniser.texts_to_sequences(X_train)\n",
|
96 |
+
"X_test = tokeniser.texts_to_sequences(X_test)\n",
|
97 |
+
"vocab_size = len(tokeniser.word_index) + 1\n",
|
98 |
+
"\n",
|
99 |
+
"X_train = tf.keras.preprocessing.sequence.pad_sequences(X_train, padding='post', maxlen=maxlen)\n",
|
100 |
+
"X_test = tf.keras.preprocessing.sequence.pad_sequences(X_test, padding='post', maxlen=maxlen)"
|
101 |
+
]
|
102 |
+
},
|
103 |
+
{
|
104 |
+
"cell_type": "code",
|
105 |
+
"execution_count": 7,
|
106 |
+
"metadata": {},
|
107 |
+
"outputs": [
|
108 |
+
{
|
109 |
+
"name": "stdout",
|
110 |
+
"output_type": "stream",
|
111 |
+
"text": [
|
112 |
+
"---------------------- Getting Glove Embeddings -------------------------\n",
|
113 |
+
"\n",
|
114 |
+
"---------------------- -------------------------\n",
|
115 |
+
"\n"
|
116 |
+
]
|
117 |
+
}
|
118 |
+
],
|
119 |
+
"source": [
|
120 |
+
"embeddings_dictionary=getGloveEmbeddings(glove_folder)\n",
|
121 |
+
"embedding_matrix = zeros((vocab_size, maxlen))\n",
|
122 |
+
"for word, index in tokeniser.word_index.items():\n",
|
123 |
+
" embedding_vector = embeddings_dictionary.get(word)\n",
|
124 |
+
" if embedding_vector is not None:\n",
|
125 |
+
" embedding_matrix[index] = embedding_vector"
|
126 |
+
]
|
127 |
+
},
|
128 |
+
{
|
129 |
+
"cell_type": "code",
|
130 |
+
"execution_count": 8,
|
131 |
+
"metadata": {},
|
132 |
+
"outputs": [
|
133 |
+
{
|
134 |
+
"name": "stdout",
|
135 |
+
"output_type": "stream",
|
136 |
+
"text": [
|
137 |
+
"Model: \"sequential\"\n",
|
138 |
+
"_________________________________________________________________\n",
|
139 |
+
" Layer (type) Output Shape Param # \n",
|
140 |
+
"=================================================================\n",
|
141 |
+
" embedding (Embedding) (None, 100, 100) 10591700 \n",
|
142 |
+
" \n",
|
143 |
+
" gru (GRU) (None, 100) 60600 \n",
|
144 |
+
" \n",
|
145 |
+
" dense (Dense) (None, 1) 101 \n",
|
146 |
+
" \n",
|
147 |
+
"=================================================================\n",
|
148 |
+
"Total params: 10652401 (40.64 MB)\n",
|
149 |
+
"Trainable params: 60701 (237.11 KB)\n",
|
150 |
+
"Non-trainable params: 10591700 (40.40 MB)\n",
|
151 |
+
"_________________________________________________________________\n",
|
152 |
+
"None\n"
|
153 |
+
]
|
154 |
+
}
|
155 |
+
],
|
156 |
+
"source": [
|
157 |
+
"model=tf.keras.models.Sequential([\n",
|
158 |
+
" tf.keras.layers.Embedding(input_dim=vocab_size,output_dim= maxlen, weights=[embedding_matrix], input_length=maxlen , trainable=False),\n",
|
159 |
+
" tf.keras.layers.GRU(maxlen),\n",
|
160 |
+
" tf.keras.layers.Dense(1, activation='sigmoid')\n",
|
161 |
+
" ]) \n",
|
162 |
+
" \n",
|
163 |
+
"print(model.summary())\n",
|
164 |
+
"\n",
|
165 |
+
"early_stop = tf.keras.callbacks.EarlyStopping(monitor='val_accuracy', mode='auto', patience=10)\n",
|
166 |
+
"\n",
|
167 |
+
"model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])"
|
168 |
+
]
|
169 |
+
},
|
170 |
+
{
|
171 |
+
"cell_type": "code",
|
172 |
+
"execution_count": 9,
|
173 |
+
"metadata": {},
|
174 |
+
"outputs": [
|
175 |
+
{
|
176 |
+
"name": "stdout",
|
177 |
+
"output_type": "stream",
|
178 |
+
"text": [
|
179 |
+
"Epoch 1/100\n",
|
180 |
+
"766/766 [==============================] - 41s 51ms/step - loss: 0.5112 - accuracy: 0.7408 - val_loss: 0.4424 - val_accuracy: 0.7906\n",
|
181 |
+
"Epoch 2/100\n",
|
182 |
+
"766/766 [==============================] - 39s 51ms/step - loss: 0.3865 - accuracy: 0.8234 - val_loss: 0.3741 - val_accuracy: 0.8330\n",
|
183 |
+
"Epoch 3/100\n",
|
184 |
+
"766/766 [==============================] - 38s 49ms/step - loss: 0.3418 - accuracy: 0.8473 - val_loss: 0.3578 - val_accuracy: 0.8444\n",
|
185 |
+
"Epoch 4/100\n",
|
186 |
+
"766/766 [==============================] - 39s 51ms/step - loss: 0.3104 - accuracy: 0.8653 - val_loss: 0.3519 - val_accuracy: 0.8446\n",
|
187 |
+
"Epoch 5/100\n",
|
188 |
+
"766/766 [==============================] - 40s 52ms/step - loss: 0.2721 - accuracy: 0.8819 - val_loss: 0.3361 - val_accuracy: 0.8510\n",
|
189 |
+
"Epoch 6/100\n",
|
190 |
+
"766/766 [==============================] - 40s 52ms/step - loss: 0.2412 - accuracy: 0.8972 - val_loss: 0.3429 - val_accuracy: 0.8540\n",
|
191 |
+
"Epoch 7/100\n",
|
192 |
+
"766/766 [==============================] - 41s 54ms/step - loss: 0.2082 - accuracy: 0.9143 - val_loss: 0.3459 - val_accuracy: 0.8570\n",
|
193 |
+
"Epoch 8/100\n",
|
194 |
+
"766/766 [==============================] - 61s 79ms/step - loss: 0.1683 - accuracy: 0.9329 - val_loss: 0.4076 - val_accuracy: 0.8528\n",
|
195 |
+
"Epoch 9/100\n",
|
196 |
+
"766/766 [==============================] - 59s 78ms/step - loss: 0.1338 - accuracy: 0.9495 - val_loss: 0.4233 - val_accuracy: 0.8490\n",
|
197 |
+
"Epoch 10/100\n",
|
198 |
+
"766/766 [==============================] - 56s 73ms/step - loss: 0.0984 - accuracy: 0.9636 - val_loss: 0.4878 - val_accuracy: 0.8514\n",
|
199 |
+
"Epoch 11/100\n",
|
200 |
+
"766/766 [==============================] - 56s 73ms/step - loss: 0.0725 - accuracy: 0.9753 - val_loss: 0.5296 - val_accuracy: 0.8413\n",
|
201 |
+
"Epoch 12/100\n",
|
202 |
+
"766/766 [==============================] - 56s 73ms/step - loss: 0.0513 - accuracy: 0.9831 - val_loss: 0.5957 - val_accuracy: 0.8437\n",
|
203 |
+
"Epoch 13/100\n",
|
204 |
+
"766/766 [==============================] - 56s 73ms/step - loss: 0.0390 - accuracy: 0.9879 - val_loss: 0.6976 - val_accuracy: 0.8336\n",
|
205 |
+
"Epoch 14/100\n",
|
206 |
+
"766/766 [==============================] - 61s 80ms/step - loss: 0.0334 - accuracy: 0.9895 - val_loss: 0.7144 - val_accuracy: 0.8468\n",
|
207 |
+
"Epoch 15/100\n",
|
208 |
+
"766/766 [==============================] - 63s 82ms/step - loss: 0.0264 - accuracy: 0.9913 - val_loss: 0.7993 - val_accuracy: 0.8417\n",
|
209 |
+
"Epoch 16/100\n",
|
210 |
+
"766/766 [==============================] - 61s 79ms/step - loss: 0.0285 - accuracy: 0.9907 - val_loss: 0.8220 - val_accuracy: 0.8445\n",
|
211 |
+
"Epoch 17/100\n",
|
212 |
+
"766/766 [==============================] - 57s 74ms/step - loss: 0.0257 - accuracy: 0.9915 - val_loss: 0.8161 - val_accuracy: 0.8396\n"
|
213 |
+
]
|
214 |
+
}
|
215 |
+
],
|
216 |
+
"source": [
|
217 |
+
"history=model.fit(x=X_train,\n",
|
218 |
+
" y=y_train,\n",
|
219 |
+
" epochs=100,\n",
|
220 |
+
" callbacks=[early_stop],\n",
|
221 |
+
" validation_split=0.3\n",
|
222 |
+
" )"
|
223 |
+
]
|
224 |
+
},
|
225 |
+
{
|
226 |
+
"cell_type": "code",
|
227 |
+
"execution_count": 10,
|
228 |
+
"metadata": {},
|
229 |
+
"outputs": [],
|
230 |
+
"source": [
|
231 |
+
"def c_report(y_true, y_pred):\n",
|
232 |
+
" print(\"Classification Report\")\n",
|
233 |
+
" print(classification_report(y_true, y_pred))\n",
|
234 |
+
" acc_sc = accuracy_score(y_true, y_pred)\n",
|
235 |
+
" print(f\"Accuracy : {str(round(acc_sc,2)*100)}\")\n",
|
236 |
+
" return acc_sc\n",
|
237 |
+
"\n",
|
238 |
+
"def plot_confusion_matrix(y_true, y_pred):\n",
|
239 |
+
" mtx = confusion_matrix(y_true, y_pred)\n",
|
240 |
+
" sns.heatmap(mtx, annot=True, fmt='d', linewidths=.5, cmap=\"Blues\", cbar=False)\n",
|
241 |
+
" plt.ylabel('True label')\n",
|
242 |
+
" plt.xlabel('Predicted label')\n",
|
243 |
+
" plt.show()"
|
244 |
+
]
|
245 |
+
},
|
246 |
+
{
|
247 |
+
"cell_type": "code",
|
248 |
+
"execution_count": 11,
|
249 |
+
"metadata": {},
|
250 |
+
"outputs": [
|
251 |
+
{
|
252 |
+
"name": "stdout",
|
253 |
+
"output_type": "stream",
|
254 |
+
"text": [
|
255 |
+
"469/469 [==============================] - 9s 18ms/step\n",
|
256 |
+
"Classification Report\n",
|
257 |
+
" precision recall f1-score support\n",
|
258 |
+
"\n",
|
259 |
+
" 0 0.82 0.87 0.85 7443\n",
|
260 |
+
" 1 0.86 0.81 0.84 7557\n",
|
261 |
+
"\n",
|
262 |
+
" accuracy 0.84 15000\n",
|
263 |
+
" macro avg 0.84 0.84 0.84 15000\n",
|
264 |
+
"weighted avg 0.84 0.84 0.84 15000\n",
|
265 |
+
"\n",
|
266 |
+
"Accuracy : 84.0\n"
|
267 |
+
]
|
268 |
+
},
|
269 |
+
{
|
270 |
+
"data": {
|
271 |
+
"image/png": "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POhcMysrSwMHDlSRIkVUvHhxPf/887r8K9Muf9koPT1dL7zwgsLCwmS32xUREaH3339fBw8edH4hX9GiRWWz2dS1a1dJksPhUExMjCpVqqTAwEDVqlVLH374ocvzfPrpp6pSpYoCAwPVrFkzlznd9cILL6hKlSoKCgpS5cqVFR0drczMzGzHTZs2TWFhYQoKClKnTp105swZl/0zZsxQ9erVVaBAAVWrVk2TJ0/2eBYAV0a8AH9hgYGBysjIcD5evXq1EhIStGrVKq1YsUKZmZlq1aqVgoODtX79em3cuFGFChVS69atnb83btw4xcXFaebMmdqwYYOSk5P18ccf5/q8TzzxhBYsWKDY2FjFx8dr2rRpKlSokMLCwrRkyRJJUkJCgk6cOKF33nlHkhQTE6M5c+Zo6tSp+umnnzRgwAB16dJFX331laSLkdWxY0e1bdtWO3bsUM+ePTV06FCP/zsJDg5WXFycfv75Z73zzjuaPn26xo8f73LM3r17tXjxYi1fvlyff/65tm/frmeffda5f968eXrllVc0evRoxcfH6/XXX1d0dLRmz57t8TwArsAC8JcQFRVltW/f3rIsy3I4HNaqVassu91uDR482Lm/dOnSVnp6uvN35s6da1WtWtVyOBzObenp6VZgYKD1xRdfWJZlWWXLlrXGjBnj3J+ZmWmVL1/e+VyWZVlNmjSx+vfvb1mWZSUkJFiSrFWrVl1xzrVr11qSrFOnTjm3paWlWUFBQdamTZtcju3Ro4f12GOPWZZlWcOGDbNq1Kjhsv+FF17IttblJFkff/xxjvvHjh1r1alTx/l4+PDhlp+fn3X06FHnts8++8zKly+fdeLECcuyLOu2226z5s+f77LOqFGjrPr161uWZVkHDhywJFnbt2/P8XkB5Ix7XoC/kBUrVqhQoULKzMyUw+HQ448/rldffdW5v2bNmi73uezcuVN79+5VcHCwyzppaWnat2+fzpw5oxMnTqhevXrOffnz59fdd9+d7aWjS3bs2CE/Pz81adLE7bn37t2rc+fO6f7773fZnpGRocjISElSfHy8yxySVL9+fbef45JFixYpNjZW+/btU0pKii5cuKDChQu7HFOhQgWVK1fO5XkcDocSEhIUHBysffv2qUePHurVq5fzmAsXLigkJMTjeQBkR7wAfyHNmjXTlClTFBAQoNDQUOXP7/o/AQULFnR5nJKSojp16mjevHnZ1ipZsuQ1zRAYGOjx76SkpEiSVq5c6RIN0sX7eLxl8+bN6ty5s0aMGKFWrVopJCRECxcu1Lhx4zyedfr06dliys/Pz2uzAn9lxAvwF1KwYEFFRES4ffxdd92lRYsWqVSpUtmuPlxStmxZffvtt2rcuLGki1cYtm7dqrvuuuuKx9esWVMOh0NfffWVWrRokW3/pSs/WVlZzm01atSQ3W7X4cOHc7xiU716defNx5d88803Vz/JP9m0aZPCw8P10ksvObcdOnQo23GHDx/W8ePHFRoa6nyefPnyqWrVqipdurRCQ0O1f/9+de7c2aPnB+AebtgFkKPOnTurRIkSat++vdavX68DBw5o3bp16tevn44ePSpJ6t+/v9544w0tXbpUu3fv1rPPPpvrZ7RUrFhRUVFR6t69u5YuXepcc/HixZKk8PBw2Ww2rVixQr/99ptSUlIUHByswYMHa8CAAZo9e7b27dunbdu26d1333XeBPv000/rl19+0ZAhQ5SQkKD58+crLi7Oo/O9/fbbdfjwYS1cuFD79u1TbGzsFW8+LlCggKKiorRz506tX79e/fr1U6dOnVSmTBlJ0ogRIxQTE6PY2Fjt2bNHP/74o2bNmqW3337bo3kAXBnxAiBHQUFB+vrrr1WhQgV17NhR1atXV48ePZSWlua8EjNo0CD9+9//VlRUlOrXr6/g4GA99NBDua47ZcoUPfLII3r22WdVrVo19erVS6mpqZKkcuXKacSIERo6dKhKly6tPn36SJJGjRql6OhoxcTEqHr16mrdurVWrlypSpUqSbp4H8qSJUu0dOlS1apVS1OnTtXrr7/u0fm2a9dOAwYMUJ8+fVS7dm1t2rRJ0dHR2Y6LiIhQx44d9eCDD6ply5a68847Xd4K3bNnT82YMUOzZs1SzZo11aRJE8XFxTlnBXB9bFZOd9UBAADchLjyAgAAjEK8AAAAoxAvAADAKMQLAAAwCvECAACMQrwAAACjEC8AAMAoxAsAADAK8QIAAIxCvAAAAKMQLwAAwCj/B/Ut7r+e94ZGAAAAAElFTkSuQmCC",
|
272 |
+
"text/plain": [
|
273 |
+
"<Figure size 640x480 with 1 Axes>"
|
274 |
+
]
|
275 |
+
},
|
276 |
+
"metadata": {},
|
277 |
+
"output_type": "display_data"
|
278 |
+
}
|
279 |
+
],
|
280 |
+
"source": [
|
281 |
+
"preds = (model.predict(X_test) > 0.5).astype(\"int32\")\n",
|
282 |
+
"c_report(y_test, preds)\n",
|
283 |
+
"plot_confusion_matrix(y_test, preds)"
|
284 |
+
]
|
285 |
+
},
|
286 |
+
{
|
287 |
+
"cell_type": "code",
|
288 |
+
"execution_count": 12,
|
289 |
+
"metadata": {},
|
290 |
+
"outputs": [
|
291 |
+
{
|
292 |
+
"name": "stderr",
|
293 |
+
"output_type": "stream",
|
294 |
+
"text": [
|
295 |
+
"d:\\STUDY\\Sem3\\deeplearning\\DLENV\\lib\\site-packages\\keras\\src\\engine\\training.py:3079: UserWarning: You are saving your model as an HDF5 file via `model.save()`. This file format is considered legacy. We recommend using instead the native Keras format, e.g. `model.save('my_model.keras')`.\n",
|
296 |
+
" saving_api.save_model(\n"
|
297 |
+
]
|
298 |
+
}
|
299 |
+
],
|
300 |
+
"source": [
|
301 |
+
"# Save the model\n",
|
302 |
+
"model.save(\"gru_movie_model.h5\")"
|
303 |
+
]
|
304 |
+
},
|
305 |
+
{
|
306 |
+
"cell_type": "code",
|
307 |
+
"execution_count": 13,
|
308 |
+
"metadata": {},
|
309 |
+
"outputs": [],
|
310 |
+
"source": [
|
311 |
+
"# Load the saved model\n",
|
312 |
+
"gru_movie_model = tf.keras.models.load_model('gru_movie_model.h5')\n",
|
313 |
+
"\n",
|
314 |
+
"# Function to predict sentiment for a given review\n",
|
315 |
+
"def gru_predict_sentiment(review):\n",
|
316 |
+
" sequence = tokeniser.texts_to_sequences([review])\n",
|
317 |
+
" sequence = tf.keras.preprocessing.sequence.pad_sequences(sequence, padding='post', maxlen=maxlen)\n",
|
318 |
+
" prediction = gru_movie_model.predict(sequence)\n",
|
319 |
+
" if prediction > 0.5:\n",
|
320 |
+
" return \"Positive\"\n",
|
321 |
+
" else:\n",
|
322 |
+
" return \"Negative\""
|
323 |
+
]
|
324 |
+
},
|
325 |
+
{
|
326 |
+
"cell_type": "code",
|
327 |
+
"execution_count": 14,
|
328 |
+
"metadata": {},
|
329 |
+
"outputs": [
|
330 |
+
{
|
331 |
+
"name": "stdout",
|
332 |
+
"output_type": "stream",
|
333 |
+
"text": [
|
334 |
+
"1/1 [==============================] - 1s 571ms/step\n",
|
335 |
+
"Review: This movie was fantastic! I loved every bit of it. \n",
|
336 |
+
"The sentiment is predicted as: Positive\n"
|
337 |
+
]
|
338 |
+
}
|
339 |
+
],
|
340 |
+
"source": [
|
341 |
+
"# Test the model prediction\n",
|
342 |
+
"example_review = \"This movie was fantastic! I loved every bit of it.\"\n",
|
343 |
+
"prediction_result = gru_predict_sentiment(example_review)\n",
|
344 |
+
"print(f\"Review: {example_review} \\nThe sentiment is predicted as: {prediction_result}\")"
|
345 |
+
]
|
346 |
+
},
|
347 |
+
{
|
348 |
+
"cell_type": "code",
|
349 |
+
"execution_count": 15,
|
350 |
+
"metadata": {},
|
351 |
+
"outputs": [
|
352 |
+
{
|
353 |
+
"name": "stdout",
|
354 |
+
"output_type": "stream",
|
355 |
+
"text": [
|
356 |
+
"1/1 [==============================] - 0s 51ms/step\n",
|
357 |
+
"Review: This movie was very bad! I hated every bit of it. \n",
|
358 |
+
"The sentiment is predicted as: Negative\n"
|
359 |
+
]
|
360 |
+
}
|
361 |
+
],
|
362 |
+
"source": [
|
363 |
+
"# Test the model prediction\n",
|
364 |
+
"example_review = \"This movie was very bad! I hated every bit of it.\"\n",
|
365 |
+
"prediction_result = gru_predict_sentiment(example_review)\n",
|
366 |
+
"print(f\"Review: {example_review} \\nThe sentiment is predicted as: {prediction_result}\")"
|
367 |
+
]
|
368 |
+
},
|
369 |
+
{
|
370 |
+
"cell_type": "code",
|
371 |
+
"execution_count": null,
|
372 |
+
"metadata": {},
|
373 |
+
"outputs": [],
|
374 |
+
"source": []
|
375 |
+
}
|
376 |
+
],
|
377 |
+
"metadata": {
|
378 |
+
"kernelspec": {
|
379 |
+
"display_name": "DLENV",
|
380 |
+
"language": "python",
|
381 |
+
"name": "python3"
|
382 |
+
},
|
383 |
+
"language_info": {
|
384 |
+
"codemirror_mode": {
|
385 |
+
"name": "ipython",
|
386 |
+
"version": 3
|
387 |
+
},
|
388 |
+
"file_extension": ".py",
|
389 |
+
"mimetype": "text/x-python",
|
390 |
+
"name": "python",
|
391 |
+
"nbconvert_exporter": "python",
|
392 |
+
"pygments_lexer": "ipython3",
|
393 |
+
"version": "3.10.11"
|
394 |
+
}
|
395 |
+
},
|
396 |
+
"nbformat": 4,
|
397 |
+
"nbformat_minor": 2
|
398 |
+
}
|
tokenizer_movie_gru.pickle
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:7ce600da938552049e3985141044107bf41171365090270f3405d9f17c7d822f
|
3 |
+
size 4549072
|