目录
一、机器学习项目流程
二、逻辑回归手写代码
2.1、数据准备【简单的两个特征的数据】
-0.017612 14.053064 0
-1.395634 4.662541 1
-0.752157 6.538620 0
-1.322371 7.152853 0
0.423363 11.054677 0
0.406704 7.067335 1
0.667394 12.741452 0
-2.460150 6.866805 1
0.569411 9.548755 0
-0.026632 10.427743 0
0.850433 6.920334 1
1.347183 13.175500 0
1.176813 3.167020 1
-1.781871 9.097953 0
-0.566606 5.749003 1
0.931635 1.589505 1
-0.024205 6.151823 1
-0.036453 2.690988 1
-0.196949 0.444165 1
1.014459 5.754399 1
1.985298 3.230619 1
-1.693453 -0.557540 1
-0.576525 11.778922 0
-0.346811 -1.678730 1
-2.124484 2.672471 1
1.217916 9.597015 0
...
2.2、code
# 自写逻辑回归
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def load_data():
df = pd.read_csv('./testSet-LR.txt', sep='\s+', header=None, engine='python')
df.insert(0, value=1.0, column="0_")
x_data = df.iloc[:,:-1]
y = df.iloc[:,[-1]]
return x_data.values,y.values
def sigmoid(x):
return 1.0 / (1 + np.exp(-x))
def grad_descent_MBGD(x_data,y):
m,n = x_data.shape
weights = np.random.normal(size=(n,1))
lr = 0.001
epochs = 500
for epoch in range(epochs):
start = 0
batch_size = 20
for step in range(int(np.ceil(m/batch_size))):
end = start + batch_size
x_data_b = x_data[start:end]
y_b = y[start:end]
# 梯度下降
y_pre = sigmoid(np.dot(x_data_b,weights))
grad = -1.0 * np.dot(x_data_b.T,y_b-y_pre)
weights = weights - lr * grad
start = end
return weights
def grad_descent_BGD(x_data,y):
m,n = x_data.shape
weights = np.random.normal(size=(n,1))
lr = 0.001
epochs = 500
for epoch in range(epochs):
# 梯度下降
y_pre = sigmoid(np.dot(x_data,weights))
grad = -1.0 * np.dot(x_data.T,y-y_pre)
weights = weights - lr * grad
return weights
def plot_scatter(x_data,y,weights):
# 样本数量
y = y.reshape(-1)
n = np.shape(x_data)[0]
# 对两类数据进行分类
x1_red, x2_red = [], []
x1_blue, x2_blue = [], []
for i in range(n):
if int(y[i]) == 1:
x1_red.append(x_data[i, 1])
x2_red.append(x_data[i, 2])
else:
x1_blue.append(x_data[i, 1])
x2_blue.append(x_data[i, 2])
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(x1_red, x2_red, s=30, c='red', marker='s')
ax.scatter(x1_blue, x2_blue, s=30, c='blue')
# 分界线
# 取概率=0.5,即线性计算为0时对应的点
# sigmoid(WX) = 0.5
# 0 = w0x0 + w1x1 + w2x2
# x2 = (-w0 - w1*x1) / w2
x1 = np.arange(-3.0, 3.0, 0.1)
x2 = (-(float)(weights[0][0]) - (float)(weights[1][0]) * x1) / (float)(weights[2][0]) # float是为了从矩阵中取出数值
ax.plot(x1, x2)
plt.xlabel('X1')
plt.ylabel('X2')
plt.show()
if __name__ == '__main__':
method = 'MBGD'
x_data,y = load_data()
if method == 'BGD':
weights = grad_descent_BGD(x_data,y)
else:
weights = grad_descent_MBGD(x_data,y)
print(weights)
plot_scatter(x_data,y,weights)
三、模型偏差与方差
3.1、什么是模型的偏差与方差
- 偏差:反映了模型在当前数据集【训练集、验证集】的拟合能力
- 方差:反映了模型在验证集的稳定性,也就是鲁棒性,因此方差是验证集的指标
3.2、模型偏差与方差怎么计算的?
1、假设一个简单的二分类猫狗图片识别系统,训练集的错误率为15%,验证集的错误率为16%,请问模型的偏差与方差是多少?
out:
偏差:训练集15%,验证集16%
方差:验证集偏差 - 训练集偏差 = 1%
判断:该模型方差较小,而偏差较大,模型 欠拟合
3.3、几种偏差与方差解决方式
3.3.1、根据偏差与方差判断模型的效果
- 训练集偏差为 1%,验证集偏差为11%
- 模型偏差为 1%,方差为10%,模型处于低偏差与高方差,模型过拟合,可以采取过拟合的解决方案
- 训练集偏差为 15%,验证集偏差为16%
- 模型偏差为 15%,方差为1%,模型处于高偏差与低方差,模型欠拟合,可以采取欠拟合的解决方案
- 训练集偏差为 15%,验证集偏差为31%
- 模型偏差为 15%,方差为16%,模型处于高偏差与高方差,可能数据、特征工程、模型出现问题了
- 训练集偏差为 0.5%,验证集偏差为0.8%
- 模型偏差为 0.5%,方差为0.3%,模型处于低偏差与低方差,模型效果很好
tip:还有一种最优偏差率的说法?
1、最优误差率的概念:
某个领域就算是领域的专家判断的误差率也有 15%,这个15%可以代表为天花板的误差率,因此模型最优的误差不再是0%,而是15%
2、实际模型的误差率:
实际模型的误差率 = 最优误差率 + 可避免误差率
3.3.2、高偏差与高方差的解决方式
重要的参考资料:关于正则化的几个问题【L1、L2、drop、BN】、 NLP中 batch normalization与 layer normalization图解
减少方差的技术
1、减少方差的技术?
1.1、从数据来讲:
1.1.1、收集更多的数据,引入合适的噪声,模型的鲁棒性增强
1.1.2、数据增强技术【通常解决数据不均衡的问题】
1.1.3、根据训练评估指标与业务经验,更改样本的输入特征【其实就是从新做特征工程】
1.2、加入正则化:
1.2.1、L1、L2 正则:在损失函数后面加上 参数绝对值或者平方值的和,通过约束参数值得大小来降低累加子项的值,
从而降低输出数据分布差异过大。
1.2.2、dropout:思想类似 RF 中的booststrap,在每一次训练的过程中对一些神经元进行随机掩码,而下一个批次
将会重新随机掩码;但是在预测的过程中,不在进行掩码,使用所有的神经元进行输出。
1.2.3、batch norm(BN层)或 layer norm:高层神经网络容易过拟合的原因在于上一层网络的输出值分布差异性较大,
且可能处于激活函数不活跃的位置,BN层可以去除均值与方差,使得数据分布差异性变小,从而降低累加子项的
值,最终降低了输出值分布的差异性;并且中心化的数据分布通常处于激活函数导数的活跃区间,加快模型的迭代
速度。【NLP中通常使用LN层,BN层在RNN效果较差,原因见下文】
tip:对于θ*X,BN 层通过降低X的值降低输出分布差异,而L1、L2通过降低θ的值降低输出分布差异。
1.3、early-stop:在验证评估指标进行判断,如果评估值在较长的时间内没有增长,反而出现下降的趋势,应当终止训练。
1.4、label smoothing:将 0-1的编码编码转化为大于0的较小值与小于1的较大值。
K = inputs.get_shape().as_list()[-1] # number of channels
return ((1-epsilon) * inputs) + (epsilon / K)
1.5、更改网络结构:
1.5.1、减少模型的参数与网络的层数【不推荐,模型递进从来是由易到难,没有反着来的说法】
1.5.2、加入残差结构、模型参数共享、剪枝等操作。
请思考几个问题:
1、使用了BN层为什么通常不再使用 L1、L2正则
2、BN层与drop-out混用后效果会 1+1>2吗?如果混用,drop-out通常与BN怎么放置?
3、Batch-size减少为什么会降低BN层的效果?
4、BN 层 与 LN层 的区别? 为什么 NLP中 BN层的效果差,而LN层的效果好?
答:文章参考:NLP中 BN层 与 LN 计算方式:
如果BN用到nlp中,由于一个mini batch中的每个句子长度不一致,存在paddding,对列缩放的话会造成误差,而LN层
则不存在这个问题。
- NLP 中 BN层 与 LN层 图解
减少偏差的技术
1、减少偏差的技术?
减少偏差的技术与减少方差的方法通常是相反的
1.1、从数据的角度:
1.1.1、根据评估指标与业务经常更改样本输入特征【重做特征工程】
1.2、从正则化的角度【不推荐】:
适当去除L1、L2、drop-out、BN层
1.3、从神经网络的角度:
1.3.1、增加模型神经元的数量与网络的层数
1.3.2、选择表征能力更强大的模型;例如:由 LSTM ---> transformer,使用预训练模型做一个fine turning