J'avais des données pour 20 000 utilisateurs de Twitter étiquetés avec le sexe, j'ai donc utilisé ces données pour prédire le sexe des utilisateurs de Twitter. Ruby est utilisé pour le traitement de texte et Python est utilisé pour l'apprentissage automatique.
La prédiction du sexe par simple apprentissage automatique utilisant le profil de Twitter n'était précise qu'à environ 60%.
Les données utilisées cette fois sont dans une langue étrangère, et le résultat sera différent du profil en japonais, mais la précision ne semble pas aussi bien. La raison pour laquelle je pense que c'est parce qu'il est difficile pour les gens de déterminer le sexe des données des utilisateurs de Twitter en premier lieu.
Ruby est utilisé pour les étapes 1 à 5 et Python pour les étapes 6.
Le code Ruby qui exécute les étapes 1 à 5 ci-dessus est le suivant. Avec une méthode comme celle-ci, les performances dépendent grandement de cette partie de traitement de texte. Il existe d'innombrables façons de le faire, et ce code fait un traitement de texte vraiment minimal.
# 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"))
J'ai essayé Naive Bayes, la régression logistique, la forêt aléatoire et les machines vectorielles de support, tous avec des résultats similaires.
Méthode | précision |
---|---|
Naive Bayes (distribution normale) | 0.5493 |
Baies naïves (Bernouy) | 0.6367 |
Retour logistique | 0.6151 |
Forêt aléatoire | 0.6339 |
Machine de vecteur de soutien | 0.6303 |
Il est à noter que chaque méthode a une hypothèse implicite sur les données d'origine, mais cette fois elle n'est pas prise en considération et les résultats sont simplement comparés.
# 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