Ich hatte Daten für 20.000 Twitter-Nutzer, die mit dem Geschlecht versehen waren, und habe diese Daten verwendet, um das Geschlecht der Twitter-Nutzer vorherzusagen. Ruby wird für die Textverarbeitung und Python für das maschinelle Lernen verwendet.
Die Geschlechtsvorhersage durch einfaches maschinelles Lernen unter Verwendung des Twitter-Profils war nur zu etwa 60% genau.
Die diesmal verwendeten Daten sind in einer Fremdsprache und das Ergebnis unterscheidet sich vom Profil auf Japanisch, aber die Genauigkeit scheint nicht so hoch zu sein. Der Grund, warum ich denke, ist, dass es für Menschen schwierig ist, das Geschlecht von Twitter-Benutzerdaten überhaupt zu beurteilen.
Ruby wird für die Schritte 1 bis 5 und Python für die Schritte 6 verwendet.
Der Ruby-Code, der die obigen Schritte 1 bis 5 ausführt, lautet wie folgt. Bei einer Methode wie dieser hängt die Leistung stark von diesem Textverarbeitungsteil ab. Es gibt unzählige Möglichkeiten, und dieser Code führt nur eine minimale Textverarbeitung durch.
# https://www.kaggle.com/crowdflower/twitter-user-gender-classification
def parse_kaggle_data
str = File.read('gender-classifier-DFE-791531.csv', encoding: 'ISO-8859-1:UTF-8')
lines = str.split("\r").map { |l| l.split(',') }
header = lines[0]
users = lines.drop(1).map { |l| header.map.with_index { |h, i| [h, l[i]] }.to_h }
users = users.select { |u| %w(female male).include?(u['gender']) && u['gender:confidence'] == '1' }
[users.map { |u| u['description'] }, users.map { |u| u['gender'] }]
end
def split_to_words(text_array)
text_array.map { |d| d.split(/([\s"]|__REP__)/) }.flatten.
map { |w| w.gsub(/^#/, '') }.
map { |w| w.gsub(/[^.]\.+$/, '') }.
map { |w| w.gsub(/[^!]!+$/, '') }.
map { |w| w.gsub(/^\(/, '') }.
map { |w| w.gsub(/^\)/, '') }.
delete_if { |w| w.length < 2 }.
map(&:downcase).sort.uniq
end
def count_words(text_array, word_array)
words_count = Hash.new(0)
text_array.each do |d|
word_array.each do |w|
if d.include?(w)
words_count[w] += 1
end
end
end
words_count
end
descriptions, genders = parse_kaggle_data
desc_words = split_to_words(descriptions)
desc_words_count = count_words(descriptions, desc_words)
filtered_desc_words = desc_words.select { |w| desc_words_count[w] > 2 && desc_words_count[w] < 500 }
desc_vectors = descriptions.map { |d| filtered_desc_words.map { |w| d.include?(w) ? 1 : 0 } }
File.write('data/description_vectors.txt', desc_vectors.map { |v| v.join(' ') }.join("\n"))
labels = genders.map do |g|
case g
when ''; 0
when 'brand'; 1
when 'female'; 2
when 'male'; 3
when 'unknown'; 4
end
end
File.write('data/labels.txt', labels.join("\n"))
Ich habe Naive Bayes, Logistic Regression, Random Forest und Support Vector Machines ausprobiert, alle mit ähnlichen Ergebnissen.
Methode | Richtigkeit |
---|---|
Naive Bayes (Normalverteilung) | 0.5493 |
Naive Buchten (Bernouy) | 0.6367 |
Logistische Rückgabe | 0.6151 |
Zufälliger Wald | 0.6339 |
Unterstützung Vektormaschine | 0.6303 |
Es sollte beachtet werden, dass jede Methode eine implizite Annahme über die Originaldaten hat, aber diesmal berücksichtigen wir dies nicht und vergleichen einfach die Ergebnisse.
# sudo yum install -y python3
# sudo pip3 install -U pip numpy sklearn ipython
import numpy as np
from sklearn.naive_bayes import GaussianNB
from sklearn.naive_bayes import BernoulliNB
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, accuracy_score
from sklearn.metrics import confusion_matrix
import pickle
description_vectors = np.loadtxt('data/description_vectors.txt')
labels = np.loadtxt('data/labels.txt')
(x_train, x_test, y_train, y_test) = train_test_split(description_vectors, labels)
clf = GaussianNB().fit(x_train, y_train)
clf = BernoulliNB().fit(x_train, y_train)
clf = LogisticRegression().fit(x_train, y_train)
clf = RandomForestClassifier().fit(x_train, y_train)
clf = SVC(C = 1.0).fit(x_train, y_train)
y_pred = clf.predict(x_test)
np.mean(y_test == y_pred)
# Grid search
# best params: {'C': 1.0, 'gamma': 'scale', 'kernel': 'rbf'}
parameters = [{'kernel': ['linear', 'rbf', 'poly', 'sigmoid'], 'C': np.logspace(-2, 2, 5), 'gamma': ['scale']}]
clf = GridSearchCV(SVC(), parameters, verbose = True, n_jobs = -1)
clf.fit(x_train, y_train)
# best params: {'max_depth': 100, 'n_estimators': 300}
parameters = [{'n_estimators': [30, 50, 100, 300], 'max_depth': [25, 30, 40, 50, 100]}]
clf = GridSearchCV(RandomForestClassifier(), parameters, verbose = True, n_jobs = -1)
clf.fit(x_train, y_train)
print(clf.best_params_)
print(clf.best_score_)
print(clf.best_estimator_)
print(classification_report(y_test, y_pred))
print(accuracy_score(y_test, y_pred))
print(confusion_matrix(y_test, y_pred))
# Model persistence
pickle.dump(clf, open('model.sav', 'wb'))
clf = pickle.load(open('model.sav', 'rb'))
Twitter User Gender Classification | Kaggle Using machine learning to predict gender
Recommended Posts