This repository has been archived by the owner on Nov 8, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 445
/
example_ensemble.py
152 lines (128 loc) · 5.12 KB
/
example_ensemble.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# ******************************************************************************
# Copyright 2017-2018 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ******************************************************************************
"""
This example uses the Amazon reviews though additional datasets can easily be substituted.
It only requires text and a sentiment label
It then takes the dataset and trains two models (again can be expanded)
The labels for the test data is then predicted.
The same train and test data is used for both models
The ensembler takes the two prediction matrixes and weights (as defined by model accuracy)
and determines the final prediction matrix.
Finally, the full classification report is displayed.
A similar pipeline could be utilized to train models on a dataset, predict on a second dataset
and aquire a list of final predictions
"""
import argparse
import numpy as np
from sklearn.metrics import classification_report
from sklearn.model_selection import train_test_split
# pylint: disable=no-name-in-module
from tensorflow.python.keras.preprocessing.sequence import pad_sequences
from tensorflow.python.keras.preprocessing.text import Tokenizer
from examples.supervised_sentiment.amazon_reviews import Amazon_Reviews
from examples.supervised_sentiment.ensembler import simple_ensembler
from nlp_architect.utils.generic import to_one_hot
from nlp_architect.utils.io import validate_existing_filepath, check_size
from .supervised_sentiment import simple_lstm, one_hot_cnn
max_fatures = 2000
max_len = 300
batch_size = 32
embed_dim = 256
lstm_out = 140
def ensemble_models(data, args):
# split, train, test
data.process()
dense_out = len(data.labels[0])
# split for all models
X_train_, X_test_, Y_train, Y_test = train_test_split(
data.text, data.labels, test_size=0.20, random_state=42
)
# Prep data for the LSTM model
tokenizer = Tokenizer(num_words=max_fatures, split=" ")
tokenizer.fit_on_texts(X_train_)
X_train = tokenizer.texts_to_sequences(X_train_)
X_train = pad_sequences(X_train, maxlen=max_len)
X_test = tokenizer.texts_to_sequences(X_test_)
X_test = pad_sequences(X_test, maxlen=max_len)
# Train the LSTM model
lstm_model = simple_lstm(max_fatures, dense_out, X_train.shape[1], embed_dim, lstm_out)
model_hist = lstm_model.fit(
X_train,
Y_train,
epochs=args.epochs,
batch_size=batch_size,
verbose=1,
validation_data=(X_test, Y_test),
)
lstm_acc = model_hist.history["acc"][-1]
print("LSTM model accuracy ", lstm_acc)
# And make predictions using the LSTM model
lstm_predictions = lstm_model.predict(X_test)
# Now prep data for the one-hot CNN model
X_train_cnn = np.asarray([to_one_hot(x) for x in X_train_])
X_test_cnn = np.asarray([to_one_hot(x) for x in X_test_])
# And train the one-hot CNN classifier
model_cnn = one_hot_cnn(dense_out, max_len)
model_hist_cnn = model_cnn.fit(
X_train_cnn,
Y_train,
batch_size=batch_size,
epochs=args.epochs,
verbose=1,
validation_data=(X_test_cnn, Y_test),
)
cnn_acc = model_hist_cnn.history["acc"][-1]
print("CNN model accuracy: ", cnn_acc)
# And make predictions
one_hot_cnn_predictions = model_cnn.predict(X_test_cnn)
# Using the accuracies create an ensemble
accuracies = [lstm_acc, cnn_acc]
norm_accuracies = [a / sum(accuracies) for a in accuracies]
print("Ensembling with weights: ")
for na in norm_accuracies:
print(na)
ensembled_predictions = simple_ensembler(
[lstm_predictions, one_hot_cnn_predictions], norm_accuracies
)
final_preds = np.argmax(ensembled_predictions, axis=1)
# Get the final accuracy
print(
classification_report(
np.argmax(Y_test, axis=1), final_preds, target_names=data.labels_0.columns.values
)
)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"--file_path", type=str, default="./", help="file_path where the files to parse are located"
)
parser.add_argument(
"--data_type", type=str, default="amazon", choices=["amazon"], help="dataset source"
)
parser.add_argument(
"--epochs",
type=int,
default=10,
help="Number of epochs for both models",
action=check_size(1, 20000),
)
args_in = parser.parse_args()
# Check file path
if args_in.file_path:
validate_existing_filepath(args_in.file_path)
if args_in.data_type == "amazon":
data_in = Amazon_Reviews(args_in.file_path)
ensemble_models(data_in, args_in)