[Stove AI] Машинное обучение 040-NLP Классификатор гендерных суждений

машинное обучение искусственный интеллект Python NLP

[Stove AI] Машинное обучение 040-NLP Классификатор гендерных суждений

(Библиотеки Python и номера версий, используемые в этой статье: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2, NLTK 3.3)

Целью этой статьи является создание классификатора, который может определить по имени, является ли человек мужчиной или женщиной. Основное предположение, на основе которого можно построить классификатор такого типа, заключается в том, что буквы после английского имени имеют очевидную гендерную ориентацию, например, буквы, оканчивающиеся на «ла», обычно являются женскими, а те, которые заканчиваются на «им», — мужскими. Поэтому мы считаем, что существует сильная корреляция между несколькими последними буквами имени и полом, поэтому мы можем построить классификационную модель и напрямую определить пол по имени.


1. Подготовьте набор данных

В библиотеке NLTK уже есть несколько документов с английскими именами, здесь мы можем загрузить их напрямую и объединить две части имен, чтобы сформировать набор данных.

# 1, 准备数据集,此次数据集来源于nltk.corpus内置的names文件
from nltk.corpus import names
male_names=[(name, 'male') for name in names.words('male.txt')]
female_names=[(name,'female') for name in names.words('female.txt')]
print(len(male_names)) # 2943
print(len(female_names)) # 5001
# 数据集中有2943个男性名字,5001个女性名字

# 看看男性和女性的名字都是哪些。。。。
print(male_names[:5])
print(female_names[:3])

# 将这些名字组成的list合并成一个数据集,第一列是名字,即features,第二列是性别,即label
dataset=np.array(male_names+female_names)
print(dataset.shape) # (7944, 2)没错

------------------вход----------------------

2943 5001 [('Aamir', 'male'), ('Aaron', 'male'), ('Abbey', 'male'), ('Abbie', 'male'), ('Abbot', 'male')] [('Abagael', 'female'), ('Abagail', 'female'), ('Abbe', 'female')] (7944, 2)

-----------------------Заканчивать-------------

Хотя здесь мы предполагаем, что существует сильная корреляция между несколькими последними буквами имени и полом, мы не уверены, что последние несколько букв являются самыми сильными, мы должны моделировать последние несколько букв, поэтому здесь мы берем последние 1 -4 буквы соответственно, а затем сформируйте столбцы функций набора данных, смоделируйте их отдельно и посмотрите, какой из них дает наилучшие результаты.

# 处理数据集
# 我们难以确定到底是姓名后面的几个字母才和性别相关性最大,
# 故而此处把后面的1-4个字母都取出来作为一个特征列
# 用pandas 貌似更容易一些
import pandas as pd
dataset_df=pd.DataFrame(dataset,columns=['name','sex'])
# print(dataset_df.info())
# print(dataset_df.head()) # 检查没有问题

for i in range(1,5): # 分别截取每个名字的后面i个字母
    dataset_df['len'+str(i)]=dataset_df.name.map(lambda x: x[-i:].lower())
    
print(dataset_df.head())# 检查没有问题

------------------ потерять --------- вывод ------

name sex len1 len2 len3 len4
0 Aamir male r ir mir amir
1 Aaron male n on ron aron
2 Abbey male y ey bey bbey
3 Abbie male e ie bie bbie
4 Abbot male t ot bot bbot

-------------------Заканчивать-------------


2. Создайте модель и обучите функции

Здесь, поскольку мы не знаем наиболее точных результатов букв после имени, мы можем только смоделировать их, чтобы увидеть производительность на тестовом наборе. Ниже приведен код:

# 分别构建分类器,并训练后再测试集上看看效果
dataset=dataset_df.values
np.random.shuffle(dataset)
rows=int(len(dataset)*0.7) # 70%为train set
train_set,test_set=dataset[:rows],dataset[rows:]

from nltk import NaiveBayesClassifier
from nltk.classify import accuracy as nltk_accuracy
for i in range(1,5): # 对每一列特征分别建模并训练
    train_X,train_y=train_set[:,i+1],train_set[:,1]
    train=[({'feature':feature},label) for (feature,label) in zip(train_X,train_y)] 
    # 后面的NaiveBayesClassifier 在train的时候需要()组成的list
    clf=NaiveBayesClassifier.train(train)
    
    # 查看该模型在test set上的表现
    test_X,test_y=test_set[:,i+1],test_set[:,1]
    test=[({'feature':feature},label) for (feature,label) in zip(test_X,test_y)] 
    acc=nltk_accuracy(clf,test)
    
    print('Number of suffix: {}, accuracy on test set: {:.2f}%'
          .format(i, 100*acc))

---------ВЫХОД------------ВЫХОД------------

Number of suffix: 1, accuracy on test set: 76.05%
Number of suffix: 2, accuracy on test set: 77.89%
Number of suffix: 3, accuracy on test set: 75.80%
Number of suffix: 4, accuracy on test set: 71.56%

----------------Заканчивать-----------------------

Отсюда видно, что наиболее точен тот случай, когда требуются только две буквы, за которыми следует только одна буква. Точность на тестовом наборе составляет около 77%.

########################резюме########################## ######

1. Подготовка набора данных в этом проекте требует больших усилий, и необходимо вынести последние N букв имени в качестве нового столбца признаков. Затем используйте эту функцию для обучения модели

2. Классификаторам, унаследованным в модуле nltk, не нужно выполнять операции преобразования текста в цифру над признаками, поэтому здесь нам не нужно использовать традиционный метод машинного обучения String to int read-hot encoding для преобразования, по оценкам что эти классификаторы nltk были интегрированы внутри этих операций преобразования.

3. При вызове метода обучения NaiveBaysClassifier необходимо обращать внимание на форму входной переменной, которая должна быть списком, состоящим из (feature dict, label), иначе во многих случаях будут возникать ошибки.

#################################################################


Примечание. Эта часть кода была загружена в (мой гитхаб), добро пожаловать на скачивание.

Использованная литература:

1. Классические примеры машинного обучения Python, Пратик Джоши, перевод Тао Цзюньцзе и Чена Сяоли.