机器学习作业 李宏毅老师——HW2 赢家还是输家问题

简介

这个作业是根据一个人口普查的数据判断年收入是否>50K。
输入有:一个人的年龄、受教育程度、职业、国籍等14项参数共2w笔
输出:这个人年收入是否>50K

思路分析

这个作业是一个二分类问题。使用逻辑回归比较好使。实际就是在线性回归的基础上加sigmoid函数,将其转化为概率。
与线性回归的主要区别在于loss函数的计算上。逻辑回归采用交叉滴的方法;线性回归采用欧氏距离的方法。

数据预处理

源数据都是干净的数据,而且格式很好,省去的很多麻烦。
直接进行数值化、归一化即可。

  1. 数值化:它很多的项中是利用字符串表示的。比如国籍这一项,内容就像这样:native-country: United-States, Cambodia, England, Puerto-Rico, Canada, Germany, Outlying-US(Guam-USVI-etc).等。为了能够让计算机处理,就需要将其数值化。
    数值化时我想到了两种解决方案,
    1.用数值表示。比如:中国=1.0,美国=2.0,英国=3.0等等。
    2.将国籍中的每个国家作为一个项,如果国籍是这个国家,则该项为1,否则是0。
    如果用方案1的话,不同的国家之间,看起来就像有联系似的,但是实际并没有。所以在作业中使用了方案2.
    ps:这里还可以用one-hot编码方式。这是我已经数据处理完之后才想到的,所以没有过多涉猎。
  2. 归一化:把数据范围尽量scale到同一个数量级上。(这里我不能肯定的给出为什么这么做。如果有小伙伴清楚,麻烦留个言Thanks♪(・ω・)ノ)。查看数据,发现实际只有6项需要归一化。

模型介绍

详见https://www.cnblogs.com/HL-space/p/10785225.html。这篇文章介绍的已经很详细了。

代码

对文件进行预处理 源文件是老师提供的官方文件,已在参考资料中提供下载
输出是两个文件。分别是answer.csv(结果)和data.csv(人口的各个数据)。

import pandas as pd
from pandas import DataFrame,Series
import numpy as np
import csv

rdf = pd.read_excel("C:/Users/帅哥/Desktop/普查数据 .xlsx")
#重写文件的列
name_list = []
name_list.append('age')
name_list.append('fnlwgt')
name_list.append('education-num')
name_list.append('capital-gain')
name_list.append('capital-loss')
name_list.append('hours-per-week')

all_array =np.array(rdf)
x,y = all_array.shape
data_array = all_array[:,:14]
#结果集
answer_list=[1 if i==[' >50K']else 0 for i in all_array[:,14:15]]
trans_array =np.transpose(data_array)#将数组翻转,用于找到项
for i in trans_array:
    for j in i:
        if type(j)  is str and j not in name_list:
            name_list.append(j)
name_list.remove(' ?')

#生成实际用的数据集
train_array = np.zeros((int(x),len(name_list)))
for i in range(x):
    train_array[i][0] = data_array[i][0]
    train_array[i][1] = data_array[i][2]
    train_array[i][2] = data_array[i][4]
    train_array[i][3] = data_array[i][10]
    train_array[i][4] = data_array[i][11]
    train_array[i][5] = data_array[i][12]
    for j in range(14):
        if data_array[i][j] in name_list:
            train_array[i][name_list.index(data_array[i][j])] = 1
for j in range(6):
    train_array[:,j]/=np.mean(train_array[:,j])
#将数据集写入文件
with open("C:/Users/帅哥/Desktop/data.csv","w",newline='') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerow(name_list)
    writer.writerows(train_array.tolist())
    csvfile.close()
#将结果集写入文件
answer = {
     'answer':answer_list}
df1 = pd.DataFrame(answer)
df1.to_csv("C:/Users/帅哥/Desktop/answer.csv",index=None)
print("over")

模型训练和验证集验证

print("开始执行")
import pandas as pd
import numpy as np
import math

data=pd.read_csv("C:/Users/帅哥/Desktop/data.csv")
answer = pd.read_csv("C:/Users/帅哥/Desktop/answer.csv")
#数据切割为训练集和测试集
array = np.array(data)
array1 = np.array(answer)
x,y = array.shape

train_num = int(0.67*x)
test_num = x-int(train_num)
train_data = array[:train_num,:]
test_data = array[train_num:,:]
train_answer = array1[:train_num]
test_answer = array1[train_num:] 

#更新参数、训练模型
bias = 0#偏置初始化
weights = np.ones(y)#权重初始化
learning_rate = 1
reg_rate = 0.0001
bg2_sum = 0#偏置值的梯度平方和
wg2_sum = np.zeros(y)#偏置的梯度平方和
#Pn = np.zeros(y)
print("开始循环处理")
epoches = 700

for times in range(epoches):
    b_g = 0
    w_g = np.zeros(y)
    for i in range(train_num):
        #计算b偏导和w偏导
       # Pn = weights.dot(train_data[i,:])+bias
       #Pn/=8
        Pn = weights.dot(train_data[i, :]) + bias 
        sigmoid = 1/(1+np.exp(-Pn))#Pn
        temp = -(train_answer[i] - sigmoid)
        
        b_g += temp
        w_g +=train_data[i,:]*temp#+2*reg_rate*weights# 这里可以加入正则项,防止过拟合
    b_g/=train_num
    w_g/=train_num
    
    #adagrad
    bg2_sum+=b_g**2
    wg2_sum+=w_g**2
    #更新权重和偏置
    bias -= learning_rate * b_g / bg2_sum ** 0.5 
    weights -= learning_rate * w_g / wg2_sum ** 0.5

    if times%10== 0:
        #print("测试点2")
        loss = 0
        acc = 0
        result = np.zeros(train_num)
        for j in range(train_num):
            #print("测试点3")
            y_pre = weights.dot(train_data[j,:])+bias
            #print("测试点4")
            sig = 1/(1+np.exp(-y_pre))
            if sig >= 0.5:
                result[j] = 1
            else:
                result[j] = 0
            if result[j] == train_answer[j]:
                acc+=1.0
        print("after {} epoches,the acc on train data:".format(times),acc/train_num)
    
# 验证模型效果
acc = 0
result = np.zeros(test_num)
for j in range(test_num):
    y_pre = weights.dot(test_data[j, :]) + bias
    sig = 1 / (1 + np.exp(-y_pre))
    if sig >= 0.5:
        result[j] = 1
    else:
        result[j] = 0
    if result[j] == test_answer[j]: 
        acc += 1.0
print("after train,the acc on test data:",acc/test_num)

结果

  1. 利用自己做的数据得出的结果
    自己处理的数据得出的结果
  2. 基于秋沐霖博主的数据集,利用自己的代码进行训练得出的结果在这里插入图片描述
  3. 同样都是数据预处理,咋就差距这么大。。。85%和92.5%的区别

参考资料

  1. 数据源
  2. 参考秋沐霖博主的文章

你可能感兴趣的:(python,python,机器学习)