python基于机器学习的姓名预测性别网页app开发

news2024/9/28 1:20:28

前言

做这个项目的起因是之前csdn给我推荐了一个问答:基于机器学习的姓名预测性别的手机app开发。我点进去发现已经有人回答了,链接点进去一看,好家伙,这不是查表算概率吗,和机器学习有半毛钱关系。而且我觉得用姓名预测性别挺扯淡的,去查了一下,发现某知名爱国企业和国外的都有提供姓名预测性别的api,看来是可以尝试做的。

吐槽完了,先上最后做出来的结果:
在这里插入图片描述
准确性还是可以的,并且支持人名批量查询,整个网页响应速度也很快。

环境

我用的是python3.10,需要安装以下包:
numpy
pandas
pypinyin
tensorflow-cpu
plotly(网页)
dash(网页)

方法

1.如何拿到人名和性别的数据集。这个我一开始去搜那篇查表文章背后所用的数据库从哪来的,在github上找到了它的人名出现频率图,但是没有找到原始数据库,据说是从什么泄露的kaifangjilu里拿出来的,我一想这tm不是违法吗,难道没有合法手段拿到这样的数据集资源了吗?我还是在github上找到了120万人名和性别的数据集:
点进去找到Chinese_Names_Corpus_Gender(120W).txt这个文件
2.如何对中文姓名进行特征提取,转化为机器能理解的语言。 这个想来想去还是决定把中文先转换为无注音的拼音,然后对每一个字母进行字母表数字的转换,事实证明确实效果不错。

具体如下图所示:
在这里插入图片描述

代码

代码分为三块,数据准备代码,数据训练代码,网页app代码。

数据准备代码

首先把下载下来的txt转换为csv文件:
在这里插入图片描述
把前面的东西去掉,然后文件后缀一改,就摇身一变成为了以逗号为分割的经典csv文件。
在这里插入图片描述
接下来开始读取处理数据:

import pandas as pd
df = pd.read_csv("test.csv")
df

这里我是在notebook里运行的,结果如下:

在这里插入图片描述

我们首先需要把性别转换为0,1表示男,女:

df['sex'].replace(['男', '女','未知'],
                        [0, 1, 2], inplace=True)

然后批量转换姓名并保存到新的csv文件中:

from pypinyin import lazy_pinyin
import time
count = 0
a1 = time.time()
for x in df['dict']:
    list_pinyin = lazy_pinyin(x) #["a","zuo"]
    c = ''.join(list_pinyin) #["azuo"]
    num_pinyin = [max(0.0, ord(char)-96.0) for char in c]
    num_pinyin_pad = num_pinyin + [0.0] * max(0, 20 - len(num_pinyin))
    df['dict'][count] = num_pinyin_pad[:15] #为了使输入向量固定长度,取前15个字符。
    count+=1
    a2 = time.time()
    if count % 10000 == 0:
        print(a2-a1)
df.to_csv('after_2.csv')

这里时间挺久的,因为数据量大,大概需要个半小时,我让它每10000个数据打印一下运行时间,可以去掉。然后有个细节就是因为要输入模型,所以要固定向量长度,即短的名字给它补0,长的名字给它截掉,一律取前十五个字母。 保存完csv之后就可以退出了。

数据训练代码

先把数据读进来,因为发现二分类表现更佳,所以我们这里排除性别为2也就是未知的名字。

import pandas as pd
import numpy as np
df = pd.read_csv('after_2.csv')
df_binary = df[df['sex']!=2]

准备输入向量:

import json
test_list = df_binary['dict'].values.tolist()
for i in range(len(test_list)):
    test_list[i] = eval(test_list[i])
X = np.array(test_list,dtype = np.float32)
y = np.asarray(df_binary['sex'].values.tolist())

其中X的形状是(1050353, 15),y的形状是(1050353,)。

划分训练集和测试集:

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,
y,test_size=0.2,random_state=0)

准备模型:

from tensorflow.keras import Sequential
from tensorflow.keras.layers import Embedding, Bidirectional, LSTM, Dense
from tensorflow.keras.optimizers import Adam

def lstm_model(num_alphabets=27, name_length=15, embedding_dim=256):
    model = Sequential([
        Embedding(num_alphabets, embedding_dim, input_length=15),
        Bidirectional(LSTM(units=128, recurrent_dropout=0.2, dropout=0.2)),
        Dense(1, activation="sigmoid")
    ])

    model.compile(loss='binary_crossentropy',
                  optimizer=Adam(learning_rate=0.001),
                  metrics=['accuracy'])

    return model

只有一层LSTM,cpu也可以轻松训练(指训练一个epoch需要半小时)

训练:

import numpy as np
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from tensorflow.keras.callbacks import EarlyStopping
# Step 1: Instantiate the model
model = lstm_model(num_alphabets=27, name_length=15, embedding_dim=256)

# Step 2: Split Training and Test Data

X_train, X_test, y_train, y_test = train_test_split(X,
                                                    y,
                                                    test_size=0.2,
                                                    random_state=0)

# Step 3: Train the model
callbacks = [
    EarlyStopping(monitor='val_accuracy',
                  min_delta=1e-3,
                  patience=5,
                  mode='max',
                  restore_best_weights=True,
                  verbose=1),
]

history = model.fit(x=X_train,
                    y=y_train,
                    batch_size=64,
                    epochs=3,
                    validation_data=(X_test, y_test),
                    callbacks=callbacks)

# Step 4: Save the model
model.save('boyorgirl.h5')

# Step 5: Plot accuracies
plt.plot(history.history['accuracy'], label='train')
plt.plot(history.history['val_accuracy'], label='val')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()

网络这一块是别人造好的轮子,我直接拿来用了,因为训练速度比较慢所以我这里只训练了三轮,训练集和测试集的准确率都在提升,已经接近0.88,说明继续训练还有提升空间:

在这里插入图片描述

网页开发代码

这块比较长,就不解释了,需要注意的是我结尾设置app是在0.0.0.0上的3000端口运行的,也就是说如果你把它部在服务器上,可以直接访问服务器的ip地址加端口号访问网页。如果是本地查看设置127.0.0.1即可。
另外需要在同目录底下准备一个faq.md的说明文件,是放在网页底部进行说明的,比如下图:
在这里插入图片描述

import os
import pandas as pd
import numpy as np
import re
from tensorflow.keras.models import load_model
from pypinyin import lazy_pinyin
import plotly.express as px
import dash
from dash import dash_table
import dash_bootstrap_components as dbc
from dash import dcc
from dash import html
from dash.dependencies import Input, Output, State

pred_model = load_model('boyorgirl.h5')

# Setup the Dash App
external_stylesheets = [dbc.themes.LITERA]
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

# Server
server = app.server

# FAQ section
with open('faq.md', 'r') as file:
    faq = file.read()

# App Layout
app.layout = html.Table([
    html.Tr([
        html.H1(html.Center(html.B('男孩或者女孩?'))),
        html.Div(
            html.Center("根据名字预测性别"),
            style={'fontSize': 20}),
        html.Br(),
        html.Div(
            dbc.Input(id='names',
                      value='李泽,李倩',
                      placeholder='输入多个名字请用逗号或者空格分开',
                      style={'width': '700px'})),
        html.Br(),
        html.Center(children=[
            dbc.Button('提交',
                       id='submit-button',
                       n_clicks=0,
                       color='primary',
                       type='submit'),
            dbc.Button('重置',
                       id='reset-button',
                       color='secondary',
                       type='submit',
                       style={"margin-left": "50px"})
        ]),
        html.Br(),
        dcc.Loading(id='table-loading',
                    type='default',
                    children=html.Div(id='predictions',
                                      children=[],
                                      style={'width': '700px'})),
        dcc.Store(id='selected-names'),
        html.Br(),
        dcc.Loading(id='chart-loading',
                    type='default',
                    children=html.Div(id='bar-plot', children=[])),
        html.Br(),
        html.Div(html.Center(html.B('关于该项目')),
                 style={'fontSize': 20}),
        dcc.Markdown(faq, style={'width': '700px'})
    ])
],
                        style={
                            'marginLeft': 'auto',
                            'marginRight': 'auto'
                        })


# Callbacks
@app.callback([Output('submit-button', 'n_clicks'),
               Output('names', 'value')], Input('reset-button', 'n_clicks'),
              State('names', 'value'))
def update(n_clicks, value):
    if n_clicks is not None and n_clicks > 0:
        return -1, ''
    else:
        return 0, value


@app.callback(
    [Output('predictions', 'children'),
     Output('selected-names', 'data')], Input('submit-button', 'n_clicks'),
    State('names', 'value'))
def predict(n_clicks, value):
    if n_clicks >= 0:
        # Split on all non-alphabet characters
        # Restrict to first 10 names only
        names = re.findall(r"\w+", value)

        # Convert to dataframe
        pred_df = pd.DataFrame({'name': names})
        list_list = []
        # Preprocess
        for x in names:
            list_pinyin = lazy_pinyin(x)
            c = ''.join(list_pinyin)
            num_pinyin = [max(0.0, ord(char)-96.0) for char in c]
            num_pinyin_pad = num_pinyin + [0.0] * max(0, 20 - len(num_pinyin))
            list_list.append(num_pinyin_pad[:15])
        # Predictions
        result = pred_model.predict(list_list).squeeze(axis=1)
        pred_df['男还是女'] = [
            '女' if logit > 0.5 else '男' for logit in result
        ]
        pred_df['可能性'] = [
            logit if logit > 0.5 else 1.0 - logit for logit in result
        ]

        # Format the output
        pred_df['name'] = names
        pred_df.rename(columns={'name': '名字'}, inplace=True)
        pred_df['可能性'] = pred_df['可能性'].round(2)
        pred_df.drop_duplicates(inplace=True)

        return [
            dash_table.DataTable(
                id='pred-table',
                columns=[{
                    'name': col,
                    'id': col,
                } for col in pred_df.columns],
                data=pred_df.to_dict('records'),
                filter_action="native",
                filter_options={"case": "insensitive"},
                sort_action="native",  # give user capability to sort columns
                sort_mode="single",  # sort across 'multi' or 'single' columns
                page_current=0,  # page number that user is on
                page_size=10,  # number of rows visible per page
                style_cell={
                    'fontFamily': 'Open Sans',
                    'textAlign': 'center',
                    'padding': '10px',
                    'backgroundColor': 'rgb(255, 255, 204)',
                    'height': 'auto',
                    'font-size': '16px'
                },
                style_header={
                    'backgroundColor': 'rgb(128, 128, 128)',
                    'color': 'white',
                    'textAlign': 'center'
                },
                export_format='csv')
        ], names
    else:
        return [], ''


@app.callback(Output('bar-plot', 'children'), [
    Input('submit-button', 'n_clicks'),
    Input('predictions', 'children'),
    Input('selected-names', 'data')
])
def bar_plot(n_clicks, data, selected_names):
    if n_clicks >= 0:
        # Bar Chart
        data = pd.DataFrame(data[0]['props']['data'])
        fig = px.bar(data,
                     x="可能性",
                     y="名字",
                     color='男还是女',
                     orientation='h',
                     color_discrete_map={
                         '男': 'dodgerblue',
                         '女': 'lightcoral'
                     })

        fig.update_layout(title={
            'text': '预测正确的可能性',
            'x': 0.5
        },
                          yaxis={
                              'categoryorder': 'array',
                              'categoryarray': selected_names,
                              'autorange': 'reversed',
                          },
                          xaxis={'range': [0, 1]},
                          font={'size': 14},
                          width=700)

        return [dcc.Graph(figure=fig)]
    else:
        return []


if __name__ == '__main__':
    app.run_server(host='0.0.0.0', port='3000', proxy=None, debug=False)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/430034.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《Kubernetes部署篇:Ubuntu20.04基于containerd部署kubernetes1.24.12单master集群》

一、架构图 如下图所示: 二、环境信息 主机名K8S版本系统版本内核版本IP地址备注k8s-master-621.24.12Ubuntu 20.04.5 LTS5.15.0-69-generic192.168.1.62master节点k8s-worker-631.24.12Ubuntu 20.04.5 LTS5.15.0-69-generic192.168.1.63worker节点k8s-worker-641…

Fast DDS 介绍

前面已经简要介绍过DDS协议规范了,接下来我们来看一个它的C实现----Fast DDS。 eProsima Fast-DDS是eprosima对于DDS的C实现,这是一个免费开源软件,遵循Apache License 2.0。eProsima Fast DDS在性能,功能和对最新版本RTPS标准&a…

Day17-对象

文章目录一 函数作业讲解二 函数版图书管理系统三 对象一 引入思考二 对象的创建和使用案例1案例2案例3案例4案例5-描述手机案例6-描述一组手机案例7-把对象作为函数的参数一 函数作业讲解 <script>//1编写函数&#xff0c;计算圆的面积和周长&#xff0c;在函数外由用户…

俄罗斯电商平台ozon的崛起,卖家可以使用测评补单方式打造爆款吗?

OZON俗称俄罗斯亚马逊&#xff0c;1998年成立&#xff0c;是俄罗斯唯一的多品类综合B2C电商平台&#xff0c;也是目前欧洲第四大电商市场。 作为俄罗斯互联网公司五强的OZON平台&#xff0c;拥有庞大的消费者群体&#xff0c;从2018年仅为480万人&#xff0c;到2021年就增长到…

【C++进阶】Makefile基础(一)

文章目录1. 环境2. 规则3. 原理4. 伪目标Makefile 其实只是一个指示 make 程序&#xff08;后面简称 make 或有时称之为 make 命令&#xff09;如何为我们工作的命令文件&#xff0c;我们说 Makefile 其实是在说 make&#xff0c;这一点要有很清晰的认识。而对于我们的项目来说…

21-CSS

目录 1.CSS是什么&#xff1f; 2.CSS基本语法 3.CSS类型 3.1.行内样式&#xff08;适用范围最小&#xff09; 3.2.内部样式&#xff08;适用范围适中&#xff09; 3.3.外部样式&#xff08;适用范围最大&#xff09; PS&#xff1a;关于缓存 3.4.多种样式优先级 4.代码…

浅析Linux Socket套接字编程中的 5 个隐患

隐患 1&#xff0e;忽略返回状态 第一个隐患很明显&#xff0c;但它是开发新手最容易犯的一个错误。如果您忽略函数的返回状态&#xff0c;当它们失败或部分成功的时候&#xff0c;您也许会迷失。反过来&#xff0c;这可能传播错误&#xff0c;使定位问题的源头变得困难。 捕…

XTDrone PX4 仿真平台|Ubuntu20.04 环境搭建失败记录

XTDrone PX4 仿真平台|Ubuntu20.04 环境搭建失败记录仿真环境搭建依赖安装ROS安装Gazebo安装MAVROS安装PX4配置仿真环境搭建 依赖安装 在使用apt安装的过程中&#xff08;包括之后ROS的安装&#xff09;&#xff0c;如果出现难以解决的依赖问题&#xff0c;可以使用aptitude …

Revit净高分析的三种方法

关于净高分析&#xff0c;就是在revit绘制模型到一定程度后&#xff0c;需要对构件的空间位置进行分析&#xff0c;如结构层高、管线净高、地下室是否满足人员车辆进出、地上部分是否满足正常的人员设备活动空间、净高是否满足设备进场安装等&#xff0c;它可以让我们提前发现不…

Codepipeline 跨账号访问 Codecommit

背景 大型企业中代码仓库通常存放在各部门开发账户中&#xff0c;而流水线则位于独立 DevOps 账户中。 本文我们将介绍如何创建跨账号访问 Codecommit 代码仓库的 Codepipeline 流水线&#xff0c;即 CodePipeline 调用另一个账号中的 Codecommit 代码仓库。 亚马逊云科技开发…

【Python_Scrapy学习笔记(十二)】基于Scrapy框架实现POST请求爬虫

基于Scrapy框架实现POST请求爬虫 前言 本文中介绍 如何基于 Scrapy 框架实现 POST 请求爬虫&#xff0c;并以抓取指定城市的 KFC 门店信息为例进行展示 正文 1、Scrapy框架处理POST请求方法 Scrapy框架 提供了 FormRequest() 方法来发送 POST 请求&#xff1b; FormReques…

阿里云ECS大测评【免费领阿里云套餐~】

送福利&#xff01;阿里云热门产品免费领&#xff08;含ECS&#xff09;&#xff0c;点击进入&#xff1a;https://click.aliyun.com/m/1000370359/ 本篇博客参与阿里云 ECS实例测评&#xff0c;这里采用阿里的C5.large计算型实例 本次对云服务器ECS产品能力的体验和建议&…

【2023最新】超详细图文保姆级教程:App开发新手入门(4)

之前章节我们已经完成了一个应用项目的导入、代码更新和代码提交和应用打包编译&#xff0c;本章继续讲述一下&#xff0c;如何在开发过程中进行代码的同步联机调试。 7 代码真机调试 7.1 纯静态CSS页面样式查看 代码调试有多种方式&#xff0c;如果是查看纯粹的静态样式&am…

价值迭代求解马尔可夫决策过程

Value Iteration Algorithm 其算法思想是: 在每一个状态s下&#xff0c; 之迭代算法流程如下&#xff1a; 初始化状态价值state value&#xff0c;即对每个状态的价值都赋一个初始值&#xff0c;一般是0 计算每一个状态-动作对的 动作价值函数&#xff0c;通常通过创建一个二维…

项目管理(PMP)考试:易混淆知识点汇总

请点击↑关注、收藏&#xff0c;本博客免费为你获取精彩知识分享&#xff01;有惊喜哟&#xff01;&#xff01; PMP考试中经常出现&#xff0c;但容易混淆的一些内容&#xff0c;包含15个会议、40个分析、6个矩阵、5个清单、5个审计、5个报告、4个分解结构、4个评估、3个日志…

谷歌人机验证Google reCAPTCHA

reCAPTCHA是Google公司推出的一项验证服务&#xff0c;使用十分方便快捷&#xff0c;在国外许多网站上均有使用。它与许多其他的人机验证方式不同&#xff0c;它极少需要用户进行各种识图验证。 它的使用方式如下如所示&#xff0c;只需勾选复选框即可通过人机验证。 虽然简单…

Python项目之中国数据可视化

文章目录关键词一、做什么二、怎么做1、获取数据&&处理数据2、数据库设计&&存储数据3、开发后端接口4、前端页面编写三、效果展示四、总结关键词 PythonDjangoPython网络爬虫echarts可视化阅读者&#xff08;Python基础、Django基础、H5基础&#xff09; 一、…

Linux学习笔记——UDP协议

文章目录UDP协议端格式UDP的特点面向数据报UDP的缓冲区基于UDP的应用层协议UDP使用注意事项16位的UDP校验和的校验原理UDP协议端格式 16位源端口号&#xff1a;数据从哪一个端口发出来的&#xff0c;也就是数据从哪一个进程发送出来的。在编写应用层代码的时候&#xff0c;用ui…

Git安装使用教程

Git - Downloadshttps://git-scm.com/downloads 安装 Git。可以在 Git 官网上下载安装包并按照提示进行安装。 GitHub或Gitee官网上注册一个账号&#xff0c;注册好后&#xff0c;桌面右键选择Git Bash&#xff0c;进行账号配置&#xff0c;命令如下&#xff1a; # 配置用户名…

spark第八章:Pyspark

系列文章目录 spark第一章&#xff1a;环境安装 spark第二章&#xff1a;sparkcore实例 spark第三章&#xff1a;工程化代码 spark第四章&#xff1a;SparkSQL基本操作 spark第五章&#xff1a;SparkSQL实例 spark第六章&#xff1a;SparkStreaming基本操作 spark第七章&#…