zoukankan      html  css  js  c++  java
  • 【火炉炼AI】机器学习040-NLP性别判断分类器

    【火炉炼AI】机器学习040-NLP性别判断分类器

    (本文所使用的Python库和版本号: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2, NLTK 3.3)

    本文的目标是构建一个分类器,从名字就判断这个人是男性还是女性。能够建立这种分类器的基本假设是英文名字后面的几个字母带有很明显的性别倾向,比如'la'结尾的一般是女性,以'im'结尾的一般是男性。故而我们认为名字的后面几个字母和性别之间有很强烈的相关性,所以可以建立一个分类模型,从名字中就可以直接判断性别。


    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转int的读热编码方式来转换,估计nltk这些分类器内部已经集成了这些转换操作。

    3,NaiveBaysClassifier在调用train方法时,需要注意输入变量的形式,必须是(特征dict,label)组成的list,否则很多情况下会出错。

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


    注:本部分代码已经全部上传到(我的github)上,欢迎下载。

    参考资料:

    1, Python机器学习经典实例,Prateek Joshi著,陶俊杰,陈小莉译

  • 相关阅读:
    mybatis3.0-[topic10-14] -全局配置文件_plugins插件简介/ typeHandlers_类型处理器简介 /enviroments_运行环境 /多数据库支持/mappers_sql映射注册
    _MyBatis3-topic06.07.08.09_ 全局配置文件_引入dtd约束(xml提示)/ 引入properties引用/ 配置驼峰命名自动匹配 /typeAliases起别名.批量起别名
    MyBatis3-topic04,05 -接口式编程
    JDBC终章- 使用 DBUtils实现增删查改- C3P0Utils数据源/QueryRunner runner连接数据源并执行sql
    [课本10.1.4]JDBC数据库连接池- C3P0数据源--通过构造方法创建数据源对象--通过配置文件创建数据源对象[推荐]
    JDBC课程5--利用反射及JDBC元数据(ResultSetMetaData)编写通用的查询方法
    JDBC课程4--使用PreparedStatement进行增删查改--封装进JDBCTools的功能中;模拟SQL注入 ; sql的date()传入参数值格式!
    本周进度总结
    本周进度总结
    大道至简读后感
  • 原文地址:https://www.cnblogs.com/RayDean/p/9805607.html
Copyright © 2011-2022 走看看