作业说明
数据:train.csv test.csv correct_answer.csv
资料:github李宏毅作业
收集到一些美国人的年龄、学历、地区等资料给你,如果是训练集,会在同一个csv中以‘income’告诉你这些人的工资收入是否超过50K。如果是测试集,工资收入会在correct_answer中,以Label形式告诉你是否为“ >50K”。
我们要做的是,通过人的14项基本信息,预测他的工资是否上50K,从而判断他是WInner or Loser。
数据清洗
我们在拿到数据的时候,其实可以看到数据集中有缺少的数据(在表格中以‘?’代替的数据)。如图,我们可以直接删除此行数据,这种方式叫做数据清洗。
但是如果在训练集中我们进行了数据清洗,其'income'的同时删去,对训练没有坏的影响。但是在测试集中也有数据不全的部分,如果我们对test清洗了,那么在test的人数会变少,就无法对于correct_answer中的答案。所以我们可以将test、correct_answer合并之后再做清洗。
数据分析
在机器学习中,我们能直接处理的都是数字,现在首要问题是将这些数据都转换成一个个数值。我们该如何处理呢?先把表格中是数字、是字符的区分开吧,分为A数据集与B数据集。
在B数据集中我们发现 'sex' 和 ‘income’ 这两列都只有两种结果,直接布尔化处理。
trainData['sex'] = (trainData['sex'] == 'male')
trainData['income'] = (trainData['income'] == ' >50K')
但是B数据集中其他数据我们就需要使用一个特别的函数,pd.get_dummies(B数据集)。这个函数的具体介绍参考:特征提取之pd.get_dummies()。
这里我们简略的解释一下,pd.get_dummies()就是将离散型特征的每一种取值都看成一种状态,若你的这一特征中有N个不相同的取值,那么我们就可以将该特征抽象成N种不同的状态,one-hot编码保证了每一个取值只会使得一种状态处于“激活态”,也就是说这N种状态中只有一个状态位值为1,其他状态位都是0。
B = pd.get_dummies(B) # 处理非字符的数据集
trainData = pd.concat([A, B], axis=1) # 将数据集A、B连接起来
在执行代码之后,我们发现原先为15列的trainData变成了100多列。这就是pd.get_dummies()导致的。他将一列的不同值也转变成了单独的一列。我们可以从下图看到,这是我中途保存的csv。
这样的数据我们还不能直接使用,因为此案例中,训练的列数会比测试的列数多一列:native_country_ Holand-Netherlands。我们要把此列删除,使测试时参数数目对应。
trainData = trainData.drop(['native_country_ Holand-Netherlands'], axis=1).values
训练
我们使用Logistic Regression逻辑回归设想这个问题。Logistic Regression和Linear Regression的差别主要在前者的输出范围是0-1,后者是任何值。我们可以这样理解,其实Logistict Regression就是将Linear Regression的公式外面再套一个函数,导致其输出在0-1之间。具体推导可以看李宏毅的机器学习视频。
|
|
由图右可知,我们先求出u1, u2, E1, E2(由E1, E2有权相加,得到E)。由于我不会打公式,都直接上图吧。u与E的公式如下:。79是逻辑回归的两分类中一份分类的数目,各自u、E的数目不一样的。
此公式的训练代码
def g_train(X, Y):
# 我们需要u1, u2, E1, E2来计算 z=w*x+b的w、b
num = X.shape[0]
cnt1 = 0
cnt2 = 0
sum1 = np.zeros((X.shape[1],)) # (101,)
sum2 = np.zeros((X.shape[1],))
for i in range(num):
if Y[i] == 1:
sum1 += X[i]
cnt1 += 1
else:
sum2 += X[i]