MXnet代码实战之正则化
来源:互联网 发布:淘宝12寸兵人 编辑:程序博客网 时间:2024/06/11 21:37
关于正则化的一些思考
机器学习的很多算法都是用多项式函数去逼近的。但是大家有没有产生疑问,为什么可以这样?这个时候只要我们想起伟大的泰勒公式,我想大家面对这个疑问心里就会舒坦很多,还记得我们在大学的时候学习高等数学当中的泰勒展开式,任何函数比如log x,lnx,1/x等等都可以用多项式去趋近。而不同的函数曲线其实就是这些基础函数的组合,自然也可以用多项式去趋近。
好,但是当多项式的项数太多的时候,函数就会过拟合,过拟合的意思就是模型在训练集上表现的很好,但是在测试集上表现的很差。这个时候,正则就派上用场了。正则就是用来惩罚函数的,不能让你学的太好,不能让你针对训练数据集拟合的太好。这个地方,我曾经迷糊了一阵,很多书上仅仅只是提到正则能够做到这一点,但是没有解释它为什么能做到这一点,正好最近有点感触,先简单说一些。对于多项式函数,过拟合的原因是项数太多,那我们可以定义一个函数加在多项式函数后面,用来保证最小化多项式函数项数,其实就是让W向量中项的个数最小化。求W向量中项的个数最小化其实就是0范数(0范数,向量中非零元素的个数)。意思就是说要让W向量中非0元素最少(为0的项最多),那就是在要求模型在保证训练误差最小化的同时保证项数最少。后面又有人把其推广到L1和L2范数(有人证明过)。
从0实现正则化例子
代码:
#!/usr/bin/env python# -*- coding:utf-8 -*-#Author: yuquanle#2017/10/11#沐神教程实战之正则化学习#本例子使用人工生成数据集from mxnet import ndarray as ndfrom mxnet import autogradfrom mxnet import gluonnum_train = 20num_test = 100num_inputs = 200# 生成数据集# 定义模型真实的参数true_w = nd.ones((num_inputs, 1)) * 0.01true_b = 0.05# ⽣成训练和测试数据集X = nd.random.normal(shape=(num_train + num_test, num_inputs))Y = nd.dot(X, true_w)Y += .01 * nd.random.normal(shape=Y.shape)X_train, X_test = X[:num_train], X[num_train:]Y_train, Y_test = Y[:num_train], Y[num_train:]# 定义⼀个函数它每次返回batch_size 个随机的样本和对应的⽬标import randombatch_size = 1def data_iter(num_examples): idx = list(range(num_examples)) random.shuffle(idx) for i in range(0, num_examples, batch_size): j = nd.array(idx[i:min(i + batch_size, num_examples)]) yield X.take(j), Y.take(j)# 初始化模型参数def get_params(): w = nd.random.normal(shape=(num_inputs, 1)) * 0.1 b = nd.zeros((1,)) for param in (w, b): param.attach_grad() return (w, b)# L2 范数正则化def L2_penalty(w, b): return (w ** 2).sum() + b ** 2# 定义训练和测试import matplotlib as mplmpl.rcParams['figure.dpi']= 120import matplotlib.pyplot as pltdef net(X, lambd, w, b): return nd.dot(X, w) + bdef square_loss(yhat, y): return (yhat - y.reshape(yhat.shape)) ** 2def SGD(params, lr): for param in params: param[:] = param - lr * param.graddef test(params, X, y): return square_loss(net(X, 0, *params), y).mean().asscalar()def train(lambd): epochs = 10 learning_rate = 0.002 params = get_params() train_loss = [] test_loss = [] for e in range(epochs): for data, label in data_iter(num_train): with autograd.record(): output = net(data, lambd, *params) # 加入L2正则,惩罚过于复杂的模型 loss = square_loss(output, label) + lambd * L2_penalty(*params) loss.backward() SGD(params, learning_rate) train_loss.append(test(params, X_train, Y_train)) test_loss.append(test(params, X_test, Y_test)) plt.plot(train_loss) plt.plot(test_loss) plt.legend(['train', 'test']) plt.show() return 'learned w[:10]:', params[0][:10], 'learend b:', params[1]# 测试# 先不用正则化,lamda=0train(0)# 使用lamda=2的正则化# train(2.5)
结果分析:
当不用正则时,训练误差下来了,但是测试误差还是很大。如图:
当使用正则时,lambad取2.5,训练集误差和测试集误差趋向一致,结果如下图:
使用Gloun
代码:
#!/usr/bin/env python# -*- coding:utf-8 -*-#Author: yuquanle#2017/10/11#沐神教程实战之正则化学习#本例子使用人工生成数据集#使用gluonfrom mxnet import ndarray as ndfrom mxnet import autogradfrom mxnet import gluonnum_train = 20num_test = 100num_inputs = 200true_w = nd.ones((num_inputs, 1)) * 0.01true_b = 0.05X = nd.random.normal(shape=(num_train + num_test, num_inputs))y = nd.dot(X, true_w)y += .01 * nd.random.normal(shape=y.shape)X_train, X_test = X[:num_train, :], X[num_train:, :]y_train, y_test = y[:num_train], y[num_train:]import matplotlib.pyplot as pltimport matplotlib as mplbatch_size = 1dataset_train = gluon.data.ArrayDataset(X_train, y_train)data_iter_train = gluon.data.DataLoader(dataset_train, batch_size, shuffle=True)square_loss = gluon.loss.L2Loss()def test(net, X, y): return square_loss(net(X), y).mean().asscalar()def train(weight_decay): learning_rate = 0.005 epochs = 10 net = gluon.nn.Sequential() with net.name_scope(): net.add(gluon.nn.Dense(1)) net.initialize() # 注意到这⾥ 'wd':weight decay # 通过优化算法的wd参数实现对模型的正则化(相当于 L2 范数正则化) trainer = gluon.Trainer(net.collect_params(), 'sgd', { 'learning_rate': learning_rate, 'wd': weight_decay}) train_loss = [] test_loss = [] for e in range(epochs): for data, label in data_iter_train: with autograd.record(): output = net(data) loss = square_loss(output, label) loss.backward() trainer.step(batch_size) train_loss.append(test(net, X_train, y_train)) test_loss.append(test(net, X_test, y_test)) plt.plot(train_loss) plt.plot(test_loss) plt.legend(['train', 'test']) plt.show() return ('learned w[:10]:', net[0].weight.data()[:, :10], 'learned b:', net[0].bias.data())train(6)
阅读全文
0 0
- MXnet代码实战之正则化
- MXnet代码实战之CNN
- mxnet实战之艺术画
- MXnet实战之线性回归
- MXnet代码实战之多类逻辑回归
- MXnet代码实战之多层感知机
- mxnet代码解析之mshadow
- mxnet代码解析之nnvm
- Java正则表达式之代码实战
- mxnet代码剖析之--mshadow篇
- mxnet代码剖析之--Storage篇
- mxnet代码剖析之--thread_engine篇
- mxnet代码剖析之--Symbol篇
- mxnet代码剖析之--StaticGraph篇
- mxnet代码剖析之--Executor篇
- mxnet代码剖析之--kvstore篇
- mxnet代码剖析之--ndarray篇
- mxnet代码解析之dependency engine
- 深入源码剖析Thread.join实现
- GoPro又裁员了,270名员工将离职
- SQL 数据定义赋值、输出
- 重载流插入和前置与后置自增运算符
- java-基础知识汇总
- MXnet代码实战之正则化
- 10.27(周五)
- 以一个实例说明 CMakeLists.txt 文件的编写
- POJ 2766 laserbox 模拟还有过不了的map+set
- NO.10 file
- 每分钟8个单词:用脑波实时聊天即将成为可能
- Trie树(字典树)的实现
- 李彦宏的“五年规划”:先让无人车变为现实,利润不重要
- python函数对象与闭包详解