李宏毅ML作业笔记2: 二分类薪资水平

本文代码只讨论核心部分,完整代码上传CSDN 资源并在kaggle 公开:

https://www.kaggle.com/laugoon/homework2

https://download.csdn.net/download/lagoon_lala/19032029

目录

任务介绍

预测思路

对率回归

数据准备

工具函数

梯度和损失

训练

作损失, 精度曲线

预测测试集

概率生成模型

准备数据

平均值和协方差

计算weights, bias

预测测试集标签

Report题目

1. 生成式/判别模型对比

2. 正则化

尝试调整原模型参数.

加入正则化

正则参数λ影响

3. 训练方式

4. 特征标准化

特征标准化原理

对模型影响

任务介绍

二元分类, 通过个人资料, 预测其年收入是否超过5万美元.

需要用到的 数据集有: train.csv, test_no_label.csv, X_train, Y_train, X_test

其中train.csv, test_no_label.csv为原始数据, X_train, Y_train, X_test为助教处理过.

X_train, X_test : 每行一个样本有510维度, 不必全部使用.

Y_train: label = 0含义为”

提交格式:

测试集27622有个样例

第一行: “id, label”

第二行以后: “id, prediction”

CSV(comma seperated values) format

评分依据为正确率

需要手刻 gradient descent 實作 logistic regression, probabilistic generative model. 也就是不能用套件.

需要达成的 分数:

Public simple baseline(1%): 0.88617

Public strong baseline(1%): 0.89052

如果给助教临时跑, 建议固定random seeds, 不然结果可能有差距.

预测思路

“這個資料集是由 UCI Machine Learning RepositoryCensus-Income (KDD) Data Set 經過一些處理而得來。

在訓練過程中,只有X_train 、Y_train 和X_test 這三個經過處理的檔案會被使用到,train.csv 和test.csv 這兩個原始資料檔則可以提供你一些額外的資訊。”

对率回归

数据准备

下載資料,並且對每個屬性做正規化,處理過後再將其切分為訓練集與發展集(development set)。

新建notebook按照自动生成的代码可以获得文件的 路径:

import os

for dirname, _, filenames in os.walk(‘/kaggle/input’):

for filename in filenames:

print(os.path.join(dirname, filename))

/kaggle/input/ml2020spring-hw2/data/X_train

写预测结果输出的时候遇到一点报错:

Read-only file system: ‘/kaggle/input/ml2020spring-hw2/output_logistic.csv’

查看最开始自动生成代码中的注释

ou can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using “Save & Run All”

更改目录.

根据获得的文件路径, 读取csv保存在 numpy数组

with open(X_train_fpath) as f:

next(f)

X_train = np.array([line.strip(‘\n’).split(‘,’)[1:] for line in f], dtype = float)#strip()表示删除掉数据中的换行符,split(’,’)则是数据中遇到’,’ 就隔开

X_train, Y_train:

(array([[33., 1., 0., …, 52., 0., 1.],

…,

[48., 0., 0., …, 0., 0., 1.]]),

array([1., 0., 0., …, 0., 0., 0.]))

对训练集测试集的X做 标准化.

if train:

X_mean = np.mean(X[:, specified_column] ,0).reshape(1, -1)#reshape(1,-1)转换为行数1, 列数根据行数计算

X_std = np.std(X[:, specified_column], 0).reshape(1, -1)

X[:,specified_column] = (X[:, specified_column] – X_mean) / (X_std + 1e-8)#(x-μ)/σ

X_train, X_mean, X_std = _normalize(X_train, train = True)

X_test, , = normalize(X_test, train = False, specified_column = None, X_mean = X_mean, X_std = X_std)#’‘做变量名合法, 作为无用的临时变量

相关知识

shape[0]:表示矩阵的行数; shape[1]:表示矩阵的列数

https://blog.csdn.net/xiasli123/article/details/102932607

reshape:

https://www.jianshu.com/p/d9df005636a6

python下划线作用:

https://blog.csdn.net/tcx1992/article/details/80105645

将数据分割为 训练集, 发展集

train_size = int(len(X) * (1 – dev_ratio))

return X[:train_size], Y[:train_size], X[train_size:], Y[train_size:]

train_size = X_train.shape[0]#训练集行数

print(‘Size of training set: {}’.format(train_size))

Size of training set: 48830

Size of development set: 5426

Size of testing set: 27622

Dimension of data: 510

工具函数

训练过程中可能重复使用

洗牌

randomize = np.arange(len(X))#arange(len(X))返回0,1…len(X)

np.random.shuffle(randomize)#shuffle()方法将序列的所有元素随机排序

return (X[randomize], Y[randomize])

相关知识: arange, shuffle

https://zhuanlan.zhihu.com/p/266619783

计算sigmoid函数作为概率

用的概率分布是高斯分布, 则P可以代入σ, 即sigmoid函数:

$$ P\left( C_{1} \middle| x \right) = \sigma\left( z \right) \ \sigma\left( z \right)= \frac{1}{1 + exp\left( {- z} \right)} $$

np.clip(1 / (1.0 + np.exp(-z)), 1e-8, 1 – (1e-8))#clip将数限定到范围1e-8和1-(1e-8)中

相关知识: clip, sigmoid函数(详细见上篇文章)

https://blog.csdn.net/weixin_44791964/article/details/100000373

对率回归

使用sigmoid函数作为P时, 输入的z为:

$$ z= {w \cdot x + b}=\sum_i w_ix_i+b $$

_sigmoid(np.matmul(X, w) + b)#matmul矩阵相乘

相关知识: matmul

https://blog.csdn.net/alwaysyxl/article/details/83050137

通过把对率回归函数的结果 四舍五入(round),得到每行X真正的预测值.

np.round(_f(X, w, b)).astype(np.int)

计算预测 精确度

acc = 1 – np.mean(np.abs(Y_pred – Y_label))#误差1/nΣ|y-y|

梯度和损失

參考李宏毅逻辑回归PPT, P12梯度及損失函數計算公式。(在notebook写公式和CSDN一样可用Tex, 很方便)

计算交叉熵作为 损失函数

y hat=1, 属于类别1, y hat=0, 属于类别2,

对以下两个分布(假设均为Bernouli两点分布)做交叉熵. Distribution p:

$$ p\left( {x = 1} \right) = {\hat{y}}^{n}\ p\left( {x = 0} \right) = {1 – \hat{y}}^{n} $$

交叉熵可衡量两个分布接近程度:

$$ H\left( {p,q} \right) = – {\sum_{x}{p\left( x \right)ln\left( {q\left( x \right)} \right)}} $$

代入似然函数可表示为:

$$ – lnL\left( {w,b} \right) = {\sum_{n}{- \left\lbrack {{\hat{y}}^{n}lnf_{w,b}\left( x^{n} \right) + \left( {1 – {\hat{y}}^{n}} \right) ln\left( {1 – f_{w,b}\left( x^{n} \right)} \right)} \right\rbrack}} $$

cross_entropy = -np.dot(Y_label, np.log(y_pred)) – np.dot((1 – Y_label), np.log(1 – y_pred))#log默认以e为底

相关知识:log(), 交叉熵(详细查阅上篇文章)

https://blog.csdn.net/weixin_44383134/article/details/87866307

计算梯度

梯度下降的更新公式

$$ w_{i}\leftarrow w_{i} – \eta{\sum_{n}{- \left( {{\hat{y}}^{n} – f_{w,b}\left( x^{n} \right)} \right)x_{i}^{n}}} $$

该公式中间的因子, 为似然函数lnL对wi的偏微分:

$$ \frac{\partial lnL\left( {w,b} \right)}{\partial w_{i}} =-\sum_{n}{ \left( {{\hat{y}}^{n} – f_{w,b}\left( x^{n} \right)} \right)x_{i}^{n}} $$

y_pred = _f(X, w, b)#对率回归

pred_error = Y_label – y_pred#误差

w_grad = -np.sum(pred_error * X.T, 1)#sum参数axis=1是压缩列,即将每一行的元素相加,将矩阵压缩为一列

b_grad = -np.sum(pred_error)

相关知识: sum(), 损失函数最小化(详见上篇)

https://zhuanlan.zhihu.com/p/85790648

训练

我們使用小批次(batch)梯度下降法來訓練。訓練資料被分為許多小批次,針對每一個小批次,我們分別計算其梯度以及損失,並根據該批次來更新模型的參數。當一次迴圈(循环, 迭代)完成,也就是整個訓練集的所有小批次都被使用過一次以後,我們將所有訓練資料打散並且重新分成新的小批次,進行下一個迴圈,直到事先設定的迴圈數量達成為止。

初始化wb

w = np.zeros((data_dim,)) #zeros第一个参数为形状

b = np.zeros((1,))

相关知识: zeros()的第一个参数shape为整数或tuple, 表示矩阵形状

https://blog.csdn.net/weixin_44805104/article/details/102746080

https://blog.csdn.net/u010852680/article/details/77745468

np.zeros((5,))与np.zeros(5)的效果相同, 都是:

array([0., 0., 0., 0., 0.])

当shape为二元组时, 则第一个数为行数, 第二个为列数, 如np.zeros((5,2))得到:

array([[0., 0.],

[0., 0.],

[0., 0.],

[0., 0.],

[0., 0.]])

计算梯度

w_grad, b_grad = _gradient(X, Y, w, b)

利用梯度下降更新参数w b,学习率随时间(step)减少

w = w – learning_rate/np.sqrt(step) * w_grad

计算Y预测值:

y_train_pred = _f(X_train, w, b)

Y_train_pred = np.round(y_train_pred)

计算精确度:

train_acc.append(_accuracy(Y_train_pred, Y_train))

计算损失值:

train_loss.append(_cross_entropy_loss(y_train_pred, Y_train) / train_size)#/ train_size消除训练集与发展集大小不同带来的影响

print(‘Training loss: {}’.format(train_loss[-1]))#[-1]表示数组中最后一位

Training loss: 0.2713554352464059

Development loss: 0.2896359675026287

Training accuracy: 0.8836166291214418

Development accuracy: 0.8733873940287504

作损失, 精度曲线

plt.plot(train_loss)# x可省略,默认[0,1..,N-1]递增

plt.plot(dev_loss)

plt.title(‘Loss’)

plt.legend([‘train’, ‘dev’])#默认参数: 图例的名称

plt.savefig(‘/kaggle/working/loss.png’)

plt.show()

相关知识: savefig

https://www.cnblogs.com/cgmcoding/p/14244735.html

李宏毅ML作业笔记2: 二分类薪资水平

李宏毅ML作业笔记2: 二分类薪资水平

预测测试集

預測測試集的資料標籤並且存在 output_logistic.csv 中。

predictions = _predict(X_test, w, b)

with open(output_fpath.format(‘logistic’), ‘w’) as f:

f.write(‘id,label\n’)

for i, label in enumerate(predictions):#enumerate列出数据和生成数据下标

f.write(‘{},{}\n’.format(i, label))

筛选最大(显著)的几个weight, 即得到 最有用的特征

ind = np.argsort(np.abs(w))[::-1]#argsort从小到大排序, ::-1从后向前读取

with open(X_test_fpath) as f:

content = f.readline().strip(‘\n’).split(‘,’)

features = np.array(content)

for i in ind[0:10]:

print(features[i], w[i])

相关知识:

argsort

https://blog.csdn.net/qq_38486203/article/details/80967696

分片

https://blog.csdn.net/ITOMG/article/details/88683256

输出的结果:

Not in universe -4.031960278019251

Spouse of householder -1.625403958705141

Other Rel

Original: https://blog.csdn.net/lagoon_lala/article/details/117136745
Author: lagoon_lala
Title: 李宏毅ML作业笔记2: 二分类薪资水平

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/635849/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球