I have below csv file called dataset.csv:
is_offensive,text
0,Hi there! My name is oliver
1,Shut up man!
0,What is wrong?
1,Go away idiot!
Which contains +5000 rows of similar annotated data.
The first column is_offensive contains the label that I want to predict, and the second column text is the actual text used for training.
After looking at the spaCy documentation, I can see that in order to train your own custom text classification model, the training data needs to look like this:
TRAINING_DATA = [
["Hi there! My name is oliver", {"OFFENSIVE": True}],
["Shup up man!", {"OFFENSIVE": True}],
["What is wrong?", {"OFFENSIVE": False}],
["Go away idiot!", {"OFFENSIVE": True}]
]
I have created the below method, to parse this CSV file and return it in the format spaCy expects:
def convert():
TRAINING_DATA = defaultdict(list)
# Open CSV file.
with open('train/profanity/data/profanity_cleaned_data.csv', mode='r') as csv_file:
csv_reader = csv.DictReader(csv_file)
line_count = 1
for row in csv_reader:
if line_count > 0 and line_count < 1000: #Read the first 1000 lines.
TRAINING_DATA['csv'].append([str(row['text']), {
'OFFENSIVE': bool(int(row['is_offensive']))}])
line_count += 1
return TRAINING_DATA['csv']
Now, to train the data, I simply do:
def train():
output_dir = 'train/profanity/model/'
TRAINING_DATA = convert()
nlp = spacy.blank("en")
category = nlp.create_pipe("textcat")
category.add_label("OFFENSIVE")
nlp.add_pipe(category)
# Start the training
nlp.begin_training()
# Loop for 10 iterations
for itn in range(10):
# Shuffle the training data
random.shuffle(TRAINING_DATA)
# Batch the examples and iterate over them
for batch in tqdm(spacy.util.minibatch(TRAINING_DATA, size=1)):
texts = [nlp(text) for text, entities in batch]
annotations = [{"cats": entities} for text, entities in batch]
nlp.update(texts, annotations)
nlp.to_disk(output_dir)
print("Saved model to", output_dir)
And then finally, to test the model on a new text:
def testModel():
test_text = "You are a very kind person."
model_dir = 'train/profanity/model/'
nlp = spacy.load(model_dir)
doc = nlp(test_text)
print(test_text, doc.cats)
The above method testModel() returns:
You are a very kind person. {'OFFENSIVE': 0.9999545812606812}
Actually, no matter what text I use as an input, I get back the OFFENSIVE label with the confidence very close to 100. However, as you can see in the input text: You are a very kind person should not be classified as OFFENSIVE
What am I doing wrong?