?人名和性别数据train.txt;text.txt 下载地址:NLP学习——人名和性别相关对应数据-自然语言处理文档类资源-CSDN下载
一,首先读取数据,并对数据进行简单处理
import pandas as pd
from collections import defaultdict
train = pd.read_csv("D:/train.txt",sep='\s+',names = ['name','sex'],encoding='utf-8') #要先知道文件的编码方式,否者无法解码
test = pd.read_csv("D:/test.txt",sep='\s+',names = ['name','sex'],encoding='UTF-8') #以多个空格为分隔符标志
##数据处理
##删除含有空数据的行,把男替换为1,女替换为0
train.dropna(axis=1)
test.dropna(axis=1)
test.loc[test['sex']=='男','sex']= 1
test.loc[test['sex']=='女','sex']= 0
train.loc[train['sex']=='男','sex'] = 1
train.loc[train['sex']=='女','sex'] = 0
二,对数据再次进行处理,并计算训练集中每个字的先验改概率
#根据性别进行分类
names_female = train[train['sex']== 0] #女性一组
names_male = train[train['sex']== 1] #男性一组
##释放内存
del train
#计算每个字在男和女中出现的概率
totals = {'f':len(names_female),'m':len(names_male)} #女性总数,男性总数
nums_list_f = defaultdict(int)
for name in names_female['name']:
for ch in name:
nums_list_f[ch] += 1.0 / totals['f']
nums_list_m = defaultdict(int)
for name in names_male['name']:
for ch in name:
nums_list_m[ch] += 1.0 / totals['m']
?三,训练集中只含有一部分字,总会有一些人的名字的字在我们的训练集中没有出现,当遇见这些名字时,以上的代码会判为这个人不存在,所以解决这个问题我们可以对数据进行拉普拉斯平滑。
#拉普拉斯平滑
def laplace(char,nums_list,totals,alpha=1): #char:字符;nums_list:字符频率表;totals:人数
count = nums_list[char]*totals #该字符出现的次数
charnums = len(nums_list) #字符表中个数
smooth = (count+alpha)/(totals+charnums)
return smooth
?四,对一个名字进行计算出是男的概率,女的概率各是多少,并返回一个字典
#拉普拉斯平滑后,一个名字是男和女的概率,并返回一个字典
def Prob(name,totals,nums_list_m,nums_list_f):
prob_m = 1;
prob_f = 1;
for ch in name:
prob_m*=laplace(ch,nums_list_m,totals['m'])
prob_f*=laplace(ch,nums_list_f,totals['f'])
prob = {'male':prob_m,'female':prob_f}
五,对prob字典里的数据进行对比,给出结果
##通过概率比对给出结果
def result(prob):
if prob['male']>prob['female']:
return 1
else:
return 0
?六,通过测试集对模型的测试得出准确率
i=0
n=0
for nam in test['name']:
predict = result(Prob(nam,totals,nums_list_m,nums_list_f))
if(predict==test.loc[n,'sex']):
i+=1
n+=1
accuracy = (i+1)/(n+1)
print('准确率为:',accuracy)
完整代码:
#coding: utf-8
import pandas as pd
from collections import defaultdict
train = pd.read_csv("D:/train.txt",sep='\s+',names = ['name','sex'],encoding='utf-8') #要先知道文件的编码方式,否者无法解码
test = pd.read_csv("D:/test.txt",sep='\s+',names = ['name','sex'],encoding='UTF-8') #以多个空格为分隔符标志
##数据处理
##删除含有空数据的行,把男替换为1,女替换为0
train.dropna(axis=1)
test.dropna(axis=1)
test.loc[test['sex']=='男','sex']= 1
test.loc[test['sex']=='女','sex']= 0
train.loc[train['sex']=='男','sex'] = 1
train.loc[train['sex']=='女','sex'] = 0
#根据性别进行分类
names_female = train[train['sex']== 0] #女性一组
names_male = train[train['sex']== 1] #男性一组
##释放内存
del train
#计算每个字在男和女中出现的概率
totals = {'f':len(names_female),'m':len(names_male)} #女性总数,男性总数
nums_list_f = defaultdict(int)
for name in names_female['name']:
for ch in name:
nums_list_f[ch] += 1.0 / totals['f']
nums_list_m = defaultdict(int)
for name in names_male['name']:
for ch in name:
nums_list_m[ch] += 1.0 / totals['m']
#拉普拉斯平滑
def laplace(char,nums_list,totals,alpha=1): #char:字符;nums_list:字符频率表;totals:人数
count = nums_list[char]*totals #该字符出现的次数
charnums = len(nums_list) #字符表中个数
smooth = (count+alpha)/(totals+charnums)
return smooth
#拉普拉斯平滑后,一个名字是男和女的概率,并返回一个字典
def Prob(name,totals,nums_list_m,nums_list_f):
prob_m = 1;
prob_f = 1;
for ch in name:
prob_m*=laplace(ch,nums_list_m,totals['m'])
prob_f*=laplace(ch,nums_list_f,totals['f'])
prob = {'male':prob_m,'female':prob_f}
return prob
##通过概率比对给出结果
def result(prob):
if prob['male']>prob['female']:
return 1
else:
return 0
##计算准确率
i=0
n=0
for nam in test['name']:
predict = result(Prob(nam,totals,nums_list_m,nums_list_f))
if(predict==test.loc[n,'sex']):
i+=1
n+=1
accuracy = (i+1)/(n+1)
print('准确率为:',accuracy)
while(1):
nam = input("请输入要预测的姓名:")
predict = result(Prob(nam,totals,nums_list_m,nums_list_f))
if(predict == 1):
print("预测结果为:男")
if(predict == 0):
print("预测结果为:女")
|