-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNotes.txt
More file actions
232 lines (173 loc) · 9.01 KB
/
Copy pathNotes.txt
File metadata and controls
232 lines (173 loc) · 9.01 KB
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
From the leture
#data processing
import praw
import pickle
import pardas
import numpy
#machine learning
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorier
from sklearn.naive_bayes import MultinomialNB
#natural language
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
from nltk.stem.snowball import SnowballStemmer
class CustomVectorizer:
""" extracts features from text and creates word vectors"""
def __init__(self, lexicons):
self.lexicons = lexicons
def transform(self, corpus):
word_vectors = []
for text in corpus:
features = []
for k, v in self.lexicons.items()
features.append(len([] w for w in word_tokenize(text)))
word_vectors.append(features)
return numpy.array(word_vectors) #smoother to process
# break into words, match with lexicons, and then match
class CyberullyingDetectionEngine:
""" Class that deals with treaining and deploying cyberbullying detection models ""
def __init__(self):
self.corpus = None
self.tags = None
self.lexicon = None
self.vectorizer = None
self.model = None
self.metrics = None
# remove non-text elements
# underscore convention to signify use only in this class
def _simpify(self, corpus):
"" Takes in a list of strings (corpus) and removes stopwords since they don't have much meaning (i.e. and the, etc.) removes
non alphanumeri characters, stemming (removes tenses by reducing to word stem""
stop_words = set(stopwords.words('english')
stemmer = SnowballStemmer('english')) #snowball more widely used
def clean (text):
text = re.sub('[^a-zA-Z0-9', ' ', text) #replace such text with nothing a/z A/Z etc.
words = [stemmer.stem(w) for w in word_tokenize(text.lower()) if w not in stop_words]
#start from word_tokenize; text.lower is lowercase; word_tokenize breaks into words and replace with stem;
# then check with stopwords and filter
return " ".join(words) #concat words with join
return [clean(text) for text in corpus]
def _model_metrics (self, features, tags) #better idea of how model is working by looking at false positives, false mnegatives
"""takes in testing data and return a dictionary of metrics """
tp = 0; #true positive
fp = 0 #false positive
tn = 0 #true negative
fn = 0 # false negative
predictions = self.model.predict(features)
for r in zip(predictions, tags): #associates with 1ns and 0s
if r[0] == 1 and r[1] == 1:
tp += 1
elif r[0] == 1 and r[1] == 0:
fp += 1
elif r[0] == 0 and r[1] == 1:
fn += 1
elif r[0] == 0 and r[1] == 0
tn += 1
precision = tp / (tp + fp)
recall = tp / (tp + fn)
#python library
reutrn {
'precision': precision
'recall': recall,
#harmonic mean (we penalize extremes)
'f1': (2*precision*recall)/precision + recall
}
# no underscore (can't use externally) (otherwise can use externally)
def _et_lexicon(self, path):
"""" takes in a path to a text file and return a set containing every word in the file"""
words = set()
with open(path) as file:
for line in file:
words.update(line.strip().split(' ')) # take word from line, remove spaces
return words
#extract line by words
def load_corpus (self, path, corpus_col, tag_col):
#this gets the text data provided
"" takes in a path to the pickled pandas dataframe, the name of corpus column, and the name of the tag column
and extracts a tagged corpus""
#imbalance classification (we have too much data skewed towards cyberbullying)
#dilute with classified twitter data
data = pandas.read_pickle(path)[[corpus,tag_col]].values
self.corpus = [row[0] for row in data]
self.tags = [row[1] for row in data]
def load_model (self, model_name):
""" loads ml model, its corresponding vectorizer, and its performance metrics"""
self.model = pickle.load(open('./models/'+model_name+'ml_model.pkl', 'rb)) # read basic
self.vectorizer = pickle.load(open('./models/'+model_name+'_vectorizer.pkl', 'rb)) # read basic
self.metrics = pickle.load(open('./models/'+model_name+'_metrics.pkl', 'rb)) # read basic
def load_lexicon (self, fname):
"""loads a set of words from a text file"""
if self.lexicon is None"
self.lexicon = {}
self.lexicon[fname] = self._get_lexicon('./data' + fname + '.txt')
def train_using_bow(self):
#bag of words reduce to word counts using word vectorizer
"" trains a model using bag of words (word counts) on the corpus and tags it""
corpus = self._simplify(self.corpus)
self.vectorizer = countVectorizer() # count words in into into
self.vectorizer.fit(corpus)
bag_of_words = self.vectorizer.transform(corpus)
x_train, x_test, y_train, y_test = train_test_split(bag_of_words, self .tags, test_size=0.2, stratify=self.tags)
#x word count, y is the resultdo the training testing split
self.model = MultinomialNB()
self.model.fit(x_train, y_train) #fit ting model
self.metrics = self._model_metrics(x_test, y_test)
def train_using_tfidf(self):
""" trains model using tf_idf weighted words counts as features"""
#will evaluate every word in vector after vectorizing (looking at how often the thing it features in english)
#(term-frequ, inverse-doc-frequency)
corpus = self._simplify(self.corpus)
self.vectorier = TfidfVectorizer()
self.vectorizer.fit(corpus)
word_vectors = self.vectorizer.transform(corpus)
x_train, x_test, y_train, y_test = train_test_split(word_vectors, self.tags, test_size = 0.2, stratify=self.tags)
self.model = MultinomialNB()
self.model.fit(x_train, y_train)
self.metrics = self._model_metrics(x_test, y_test)
def train_using_custonm(self):
""" Trains model using a custom feature extraction approach"""
corpus = self._simplify(self.corpus)
self.vecotrizer = self.CustomVectorizer(self.lexicons)
word_vectors = self.vectorizer.transform(corpus)
x_train, x_test, y_train, y_test = train_test_split(word_vectors, self.tags, test_size = 0.2, stratify = self.tag)
#curse of dimensionality
self.model = SVC() #support vector classifier
def predict (self, corpus):s
""" takes in a text corpus and returns predictions"""
x = self.vectorizer.transform(self._simplify(corpus))
return self.model.predict(x)
def evaluate (self):
""" return model """
return self._model_metrics
def save_model(self, model_name): # won't work under self save?
""" saves the model for future use """
pickle.dump(self.model, open('./models/' + model_name + '_ml_model.pkl', 'wb')) # allows python to write to computer basic
pickle.dump(self.vectorizer, open('.models/' + model_name + '_vectorizer.pkl', 'wb'))
pickle.dump(self.metrics, open('./models/' + model_name + '_metrics.pkl', 'wb'))
if __name__ == '_main_': # only use if testing, not as part of other
reddit = praw.Reddit(
client_id = ''
client_secret = ''
user_agent = 'coffe n code cyberbulyingmodel'
)
new_comment = reddit.subreddit('TwoXCromosomes').comments(limit = 1000)
queries = [comment.body for comment in new_comments]
engine = CyberbullyingDetecitonEngine()
engine.load_corpus('./data/final_labelled_data.pkl','tweet','class')
engine.train_using_bow()
engine.save_model('bow')
print(engine.evaluate())
print(engine.predict(queries))
engine.train_using_tfidf()
engine.save_model('tfidf')
print(engine.evaluate())
print(engine.predict(queries)) #long because training two models
#you can 'rFp_Q
engine.train_using_custom()
print(engine.evaluate())
print(engine.predict(queries))
#bag (most are not cyberbullying, but still high 30 examples)
#tfidf (recall lower, precision higher, less cyberbully8ng, but can't trust metrics too much)
# reddit.com/prefs/apps/