tensorflow实现线性模型和sklearn的线性模型比较
自己用tensorflow实现了linear模型,但是和sklearn提供的模型效果相比,实验结果差了很多,所以尝试了修改优化算法,正则化,损失函数和归一化,记录尝试的所有过程和自己的实验心得。
import numpy as np
import tensorflow as tf
import sklearn
import pandas as pd
class Model:
    def __init__(self, sess, feature_size, step, learning_rate, regulation):
        self.sess = sess
        self.feature_size = feature_size
        self.step = step
        self.learning_rate = learning_rate
        self.regulation = regulation
        self.build_model()
        self.add_loss()
        self.add_optimizer()
        self.sess.run(tf.global_variables_initializer())
        self.sess.run(tf.local_variables_initializer())
    def build_model(self):
        self.x = tf.placeholder(shape=[None, self.feature_size], dtype=tf.float32)
        self.y_true = tf.placeholder(shape=[None, 1], dtype=tf.float32)
        with tf.name_scope('linear_model'):
            l2_reg = tf.contrib.layers.l2_regularizer(0.1)
            self.w = tf.get_variable(name='w', shape=[self.feature_size, 1],
                                     initializer=tf.truncated_normal_initializer(), regularizer=l2_reg)
            self.b = tf.get_variable(name='b', shape=[1],
                                     initializer=tf.truncated_normal_initializer(stddev=1, seed=1))
            self.y_pred = tf.matmul(self.x, self.w) + self.b
    def add_loss(self, loss='l2'):
        reg_variables = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
        if loss == 'l2':
            self.loss = tf.reduce_mean(tf.square(self.y_true - self.y_pred))
        if loss == 'l1':
            self.loss = tf.reduce_mean(tf.abs(self.y_true - self.y_pred))
        if loss == 'huber':
            delta = tf.constant(0.25)  # delta越大两边线性部分越陡峭,损失越大
            self.loss = tf.multiply(tf.square(delta), tf.sqrt(1. + tf.square((self.y_true - self.y_pred) / delta)) - 1.)
        self.loss += tf.add_n(reg_variables)
    def add_optimizer(self):
        self.optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
        self.train_step = self.optimizer.minimize(self.loss)
    def predict(self, x_test):
        self.pred_test = tf.matmul(tf.cast(x_test, tf.float32), self.w) + self.b
        pred_test = self.sess.run([self.pred_test])
        return pred_test
    def train(self, train_data, train_label):
        loss, y_pred = self.sess.run([self.loss, self.y_pred], feed_dict={self.x: train_data, self.y_true: train_label})
        return loss, y_pred
if __name__ == '__main__':
    feature_size, step, learning_rate, regulation = 100, 1000, 0.0001, 'L2'
    sample_size = 30
    x = [list(np.random.rand(feature_size)) for _ in range(sample_size)]
    y = [np.random.rand(1) for _ in range(sample_size)]
    x = pd.DataFrame(x).apply(lambda x: (x - np.mean(x)) / (np.max(x) - np.min(x))).values
    with tf.Session() as sess:
        model = Model(sess, feature_size, step, learning_rate, regulation)
        _, _ = model.train(x, y)
        # print('loss is ', loss)
        pred_test = model.predict(x)
        # print('pred label\tture label')
        # for each in zip(pred, y):
        #     print(round(each[0][0], 6), '\t', round(each[1][0], 6))
        loss = sum([(each[0][0] - each[1][0]) ** 2 for each in zip(pred_test, y)])
        print('LR net loss ', loss)
    from sklearn import linear_model
    reg = linear_model.LinearRegression()
    reg.fit(x, y)
    pred_test1 = reg.predict(x)
    loss = sum([(each[0][0] - each[1][0]) ** 2 for each in zip(pred_test1, y)])
    print('sklearn loss ', loss)
    import matplotlib.pyplot as plt
    fig = plt.figure()
    x = [i for i in range(len(x))]
    plt.plot(x, y, 'k*-', markersize=12)
    plt.plot(x, [each[0] for each in pred_test[0]], 'r.-', markersize=12)
    plt.plot(x, [each[0] for each in pred_test1], 'b.-', markersize=12)
    plt.legend(('true', 'my', 'Linear Fit'), loc='lower right')
    plt.title('regression compare')
    plt.show()
以下是实验记录:
权重的初始化很重要,初始化成为为0,结果全为0,初始化阶段的正太分布,结果全为负数
GradientDescentOptimizer
LR net loss  [74.816734]
sklearn loss  4.22780141391886e-30
MomentumOptimizer
LR net loss  [1.5802944]
sklearn loss  2.1308488904700377e-30
如果数据是稀疏的,用以下四种算法,同时保证可以更快的退出鞍点,用Adam算法,加入动量。
https://segmentfault.com/a/1190000012668819
AdagradOptimizer 对稀疏数据很友好
LR net loss  [19.184008]
sklearn loss  1.1571757477856268e-29
RMSPropOptimizer
LR net loss  [1.3790985]
sklearn loss  5.1738182026018704e-30
AdadeltaOptimizer 结果会非常不稳定
LR net loss  [16.51035]
sklearn loss  7.90786835165399e-30
AdamOptimizer
LR net loss  [0.98462635]
sklearn loss  5.571330143123396e-30
总结: 使用RMS,Ada系列的优化器会使结果好一些,但是这几种不同的优化器之间的效果差距不大。 一般选用Adam优化器
AdamOptimizer + 加入L2正则化项
LR net loss  [0.0768552]
sklearn loss  4.7639803104362666e-30
使模型权重变小,结果更平滑。
AdamOptimizer + 加入L1正则化项
LR net loss  [5.0768552]
sklearn loss  4.7639803104362666e-30
L1正则化效果很差,我猜测是因为正则化使权重稀疏,结果主要收到个别权重影响,但是个别的权重学习不好,所以整体效果不好。
同时L1正则化的梯度恒定,有可能在梯度下降中不收敛。
L1对异常点的容忍度很高,模型不容易过拟合。所以整体应该是欠拟合。
AdamOptimizer + 加入L2正则化项 + huber 损失(之前默认L2损失)
LR net loss  [0.58679754]
sklearn loss  3.3163743270370446e-29
使用huberloss,加大对异常点的容忍,使损失较小的时候梯度平滑。
AdamOptimizer + 加入L2正则化项 + L2 损失 + 归一化
LR net loss  [0.989549]
sklearn loss  1.8846380063795735e-29
归一化的作用:1. 模型需要 2.较少数值影响 3. 归纳分布 4.促进模型收敛 5. 减速模型的梯度收敛
https://www.cnblogs.com/silence-tommy/p/7113498.html
神经网络训练开始前,都要对数据做一个归一化处理,归一化有很多好处,原因是网络学习的过程的本质就是学习数据分布,一旦训练数据和测试数据的分布不同,那么网络的泛化能力就会大大降低.
每一批次的数据分布如果不相同的话,那么网络就要在每次迭代的时候都去适应不同的分布,这样会大大降低网络的训练速度,这也就是为什么要对数据做一个归一化预处理的原因。另外对图片进行归一化处理还可以处理光照,对比度等影响。
由此又可以引出来神经网络的BN层结构。
事实上BN用于解决多层神经网络的传递的数据分布不均衡问题。 在线性回归中无法使用。
AdamOptimizer + 加入L2正则化项 + L2 损失 + 归一化 +  修改infer的方式
LR net loss  [1.4737219]
sklearn loss  8.079969451484434e-29

到此,整个实验就结束了。 最后我自己用tensorflow实现的linear还是比不过sklean提供的线性模型。即使是loss很小,但是画图可以观察到我的模型结果很不稳定。
所以我专门去看了sklearn的源码。linear源码:数据预处理和稀疏矩阵处理,如果是稀疏的,直接用稀疏矩阵的最小二乘法,如果是普通的直接用scipy的最小二乘法。但是又被scipy封装了, 这样就没有办法继续看了。
tensorflow实现线性模型和sklearn的线性模型比较的更多相关文章
- Java内存模型和JVM内存管理
		
Java内存模型和JVM内存管理 一.Java内存模型: 1.主内存和工作内存(即是本地内存): Java内存模型的主要目标是定义程序中各个变量的访问规则,即在JVM中将变量存储到内存和从内存中取 ...
 - 从零3D基础入门XNA 4.0(2)——模型和BasicEffect
		
[题外话] 上一篇文章介绍了3D开发基础与XNA开发程序的整体结构,以及使用Model类的Draw方法将模型绘制到屏幕上.本文接着上一篇文章继续,介绍XNA中模型的结构.BasicEffect的使用以 ...
 - NOSQL数据模型和CAP原理
		
NOSQL数据模型和CAP原理 http://blog.sina.com.cn/s/blog_7800d9210100t33v.html 我本来一直觉得NoSQL其实很容易理解的,我本身也已经对NoS ...
 - 网络知识学习1---(基础知识:ISO/OSI七层模型和TCP/IP四层模型)
		
以下的内容和之后的几篇博客只是比较初级的介绍,想要深入学习的话建议自己钻研<TCP/IP详解 卷1:协议> 1.ISO/OSI七层模型 下四层是为数据传输服务的,物理层是真正的传输数 ...
 - 黑马-----内存模型和volatile详解
		
黑马程序员:Java培训.Android培训.iOS培训..Net培训 JAVA线程-内存模型和volatile详解 一.单核内存模型 1.程序运行时,将临时数据存放到Cache中 2.将CPU计算所 ...
 - 系统间通信(5)——IO通信模型和JAVA实践 下篇
		
7.异步IO 上面两篇文章中,我们分别讲解了阻塞式同步IO.非阻塞式同步IO.多路复用IO 这三种IO模型,以及JAVA对于这三种IO模型的支持.重点说明了IO模型是由操作系统提供支持,且这三种IO模 ...
 - 复杂领域的Cynefin模型和Stacey模型
		
最近好奇“复杂系统”,收集了点资料,本文关于Cynefin模型和Stacey模型.图文转自互联网后稍做修改. Cynefin模型提供一个从因果关系复杂情度来分析当前情况而作决定的框架,提出有五个领域: ...
 - 异步IO模型和Overlapped结构
		
.NET中的 Overlapped 类 异步IO模型和Overlapped结构(http://blog.itpub.net/25897606/viewspace-705867/) 数据结构 OVERL ...
 - (转载)OSI七层参考模型和TCP/IP四层参考模型
		
Mallory 网络模型概念浅析 网络模型一般是指OSI七层参考模型和TCP/IP四层参考模型. #只是一种设计==模型# Open System Interconnect的缩写,意为开放式系统互 ...
 
随机推荐
- 深入理解 ajax系列第一篇(XHR 对象)
			
1999年,微软公司发布了IE5, 第一次引入新功能:允许javascript 脚本向服务器发起 hffp 请求.这个功能方式并没有被引起注意,知道2004年 Gmail 发布和 Google Map ...
 - tf.reduce_max 与 reduce 系列  API
			
reduce 可以理解为 python 里的 reduce 函数: tensorflow 中有很多 reduce_ API,其用法完全相同 tf.reduce_max 以这个为例进行说明 def re ...
 - npm安装包时报错:Error: EPERM: operation not permitted, rename
			
解决方法:先执行 npm cache clean -force在安装需要的包.
 - Assign the task-HDU3974  dfs序+线段树
			
题意: 一个公司有n个员工,每个员工都有一个上司,一个人下属的下属也是这个人的下属,因此可将他们的关系看成一棵树, 然后给定两种操作,C操作是查询当前员工的工作,T操作是将y工作分配给x员工,当一个人 ...
 - jQuery常用操作(待续)
			
1. input清空内容 <1> $("#选择器id").val(""); <2> $("input[name='input框 ...
 - c++多态性及多态的内部实现(翁恺c++公开课[23-24])
			
多态是在父类函数的前面加上 “virtual” 关键字,使子类与父类同名的函数产生一种联系: 多态会用到两个特性:向上造型.动态绑定 向上造型是指:拿一个子类对象当作父类来看待,比如下边代码中的子类E ...
 - vim锁定,不能动
			
在vim中 ctrl+s是锁屏命令, ctrl+q是解锁
 - 正确使用 Android 的 Theme 和 Style
			
原文:http://www.tuicool.com/articles/ZjEZFj Android 5.0 可以给一个 View 单独设置一个 theme 了,其主要用途就是用在 ToolBar 上, ...
 - redhat 7.6 密码破解(无光盘)
			
开机,在下面界面按e 找到linux16 在最尾输入 rd.break 按 Ctrl+x 输入 mount -o remount,rw /sysroot 输入chroot /sysroot sh ...
 - XML规范化(DTD)
			
无意义的XML 之前说过因为xml没有预设的标签,所以说你怎麽写他一般都不会报错. 所以需要对xml的书写格式进行一些限制,这就引入了DTD 下面的这个xml你可以给book添加各种属性还不会报错,但 ...