В последнее время я работаю над проектом, который требует анализа настроений в Твиттере. Я использую наивный байесовский классификатор из библиотеки Textblob и пытаюсь обучить его 1,6 миллионам твитов (их можно найти здесь, если кому-то интересно: https://www.kaggle.com/kazanova/sentiment140). Простая передача 1,6 миллиона твитов вызывает ошибку памяти, поэтому я решил разделить ее на части, чтобы одновременно обучалось только 1000 твитов. Это имеет небольшой успех, так как я могу получить только около 10 000 твитов на своем локальном компьютере, пока мой компьютер не зависнет, потому что я использую слишком много оперативной памяти. Затем я попробовал это на Google colab, чтобы я мог запустить свой код в облаке. Как с TPU, так и с GPU, максимум, который я получил, составляет 28 000 твитов, прежде чем сеанс потерпел крах, и мне пришлось перезапустить среду выполнения. Вот мой код:
with open("shuffledlist.pickle", 'rb') as f: #Loading in my list of 1.6 million tweets
full_data = pickle.load(f)
training_data = (tweet for tweet in full_data[:1500000])
try:
with open("sentimentclassifier.pickle", "rb") as file: #makes a new classifier if one doesnt exist
classifier = pickle.load(file)
print("Got existing classifier")
except EOFError:
classifier = NaiveBayesClassifier(full_data[:1000])
print("Made new classifier")
del full_data
feeding_size = 1000
left_splice = 0
right_splice = feeding_size + left_splice
count = 0
new_start_time = time.time()
past_times = 0
while right_splice < 1500000:
loop_time = time.time()
data = itertools.islice(training_data,left_splice,right_splice)
try:
classifier.update(data)
except Exception:
print("Houston we got a problem")
with open("sentimentclassifier.pickle", "wb") as sentiment:
pickle.dump(classifier, sentiment, protocol = -1)
sys.exit("Yo it ended at {} and {}".format(left_splice, right_splice))
past_times += time.time() - loop_time
count += 1
string = "Left: {} Right: {}. Took {} seconds. Total Time Elapsed: {}. Average Time for each: {}. Count: {}."\
.format(left_splice, right_splice, time.time()-loop_time, time.time() - new_start_time, past_times/count, count)
sys.stdout.write('\r' + string)
left_splice += feeding_size
right_splice += feeding_size
with open("sentimentclassifier.pickle", "wb") as sentiment:
pickle.dump(classifier, sentiment, protocol = -1)
print("Done dumping cycle {}!".format(count))
print("Done! Right: {}, Left: {}!".format(left_splice, right_splice))
with open("sentimentclassifier.pickle", "wb") as sentiment:
pickle.dump(classifier, sentiment, protocol = -1)
print("Training took {} seconds!".format(time.time()-new_start_time))
Некоторые примечания:
Поскольку моя основная проблема заключается в размере моего файла sentimentclassifier.pickle, я попытался использовать gzip, но это просто слишком долго, чтобы открыть и закрыть файл, и это особенно плохо, потому что мне нужно открывать файл каждые l oop, так как я не хочу потерять какой-либо прогресс в случае сбоя программы.
Я перешел от использования списков к использованию генераторов, что значительно улучшило скорость.
В google colab я пытался передавать по 10 000 за раз, что было из последних усилий, и неудивительно, что это не сработало к лучшему.
Я не уверен, является ли наивный байесовский классификатор nltk более эффективным, но я действительно хочу, чтобы это было последнее средство, поскольку переформатирование моего списка твитов может занять несколько часов. Но если это действительно будет более эффективно, я с радостью переделаю свой код, если это будет означать, что я смогу заставить это работать.
Спасибо, и любые советы будут высоко оценены!