• 使用线性回归识别sklearn中的手写数字digit


    从昨天晚上,到今天上午12点半左右吧,一直在调这个代码。最开始训练的时候,老是说loss:nan

    查了资料,因为是如果损失函数使用交叉熵,如果预测值为0或负数,求log的时候会出错。需要对预测结果进行约束。

    有一种约束方法是:y_predict=max(y,(0,1e-18])。也就是将小于0的数值随机分配为(0,1e-18]中的某个数。这样做好像不太合适。

    还有一种方法是使用sigmoid作为激活函数。我这样改正了之后仍然没有效果。

    后来我把数据集中的图片打开看了一下才发现,它跟mnist不一样,是彩色的,matplot告诉我说是24位彩色,但是颜色值最大是16

    把颜色规范化之后,在训练,准确度在0.93左右。

    首先是线性回归类:

    import tensorflow as tf
    import numpy as np
    class myLinearModel:
        def __init__(self,x_dimen):
            self.x_dimen=x_dimen
            self.epoch=0
            self._num_datas=0
            self.datas=None
            self.lables=None
            self.constructModel()
        def get_weiInit(self,shape):
            weiInit=tf.truncated_normal(shape,1.,1.)
            #weiInit=tf.constant(10.,shape=shape)
            return tf.Variable(weiInit)
        def get_biasInit(self,shape):
            biasInit=tf.constant(0.1,shape=shape)
            return tf.Variable(biasInit)
        def constructModel(self):
            self.x = tf.placeholder(dtype=tf.float32,shape=[None,self.x_dimen])
            self.y=tf.placeholder(dtype=tf.float32,shape=[None,10])
            self.weight=self.get_weiInit([self.x_dimen,10])
            self.bias=self.get_biasInit([10])
            self.y_pre=tf.nn.softmax(tf.matmul(self.x,self.weight)+self.bias)
            #self.loss=tf.reduce_mean(tf.squared_difference(self.y_pre,self.y))
            self.correct_mat=tf.equal(tf.argmax(self.y_pre,1),tf.argmax(self.y,1))
            self.loss=-tf.reduce_sum(self.y*tf.log(self.y_pre))
            self.train_step = tf.train.GradientDescentOptimizer(0.001).minimize(self.loss)
            self.accuracy=tf.reduce_mean(tf.cast(self.correct_mat,"float"))
        def next_batch(self,batchsize):
            start=self.epoch
            self.epoch+=batchsize
            if self.epoch>self._num_datas:
                perm=np.arange(self._num_datas)
                np.random.shuffle(perm)
                self.datas=self.datas[perm]
                self.lables=self.lables[perm]
                start=0
                self.epoch=batchsize
            end=self.epoch
            return self.datas[start:end],self.lables[start:end]
        def one_hot(self,labels,class_num):
            b=tf.one_hot(labels,class_num,1,0)
            with tf.Session() as sess:
                return sess.run(b)
    
        def train(self,x_train,y_train,x_test,y_test):
            self.datas=x_train
            #self.lables=self.one_hot(y_train.reshape(1,-1).tolist()[0],10)
            self.lables = y_train
            self._num_datas=(self.lables.shape[0])
            with tf.Session() as sess:
                sess.run(tf.global_variables_initializer())
                for i in range(3000):
                    batch=self.next_batch(100)
                    sess.run(self.train_step,feed_dict={
                        self.x:batch[0],
                        self.y:batch[1]
                    })
                    if 1:
                        train_loss = sess.run(self.loss, feed_dict={
                            self.x: batch[0],
                            self.y: batch[1]
                        })
                        print("setp %d,test_loss %f" % (i, train_loss))
                        #print("y_pre",sess.run(self.y_pre,feed_dict={self.x: batch[0],self.y: batch[1]}))
                        #print("y is", sess.run(self.y, feed_dict={self.x: batch[0],self.y: batch[1]}))
                        #print("correct_mat",sess.run(self.correct_mat,feed_dict={self.x: batch[0],self.y: batch[1]}))
                        #print("*****************weight********************",sess.run(self.weight))
                print(sess.run(self.accuracy,feed_dict={self.x:x_test,self.y:y_test}))
    View Code

    这里做的就是普通的线性回归:y_predict = w*x+bias ,用交叉熵做损失函数

    然后是我的运行类:

    from myTensorflowLinearModle import myLinearModel as mlm
    import tensorflow as tf
    from sklearn.cross_validation import train_test_split
    from sklearn.datasets import load_digits
    import matplotlib.pyplot as plt
    # import tensorflow.examples.tutorials.mnist.input_data as input_data
    # mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
    
    
    def one_hot(labels, class_num):
        b = tf.one_hot(labels, class_num, 1, 0)
        with tf.Session() as sess:
            return sess.run(b)
    def normal(x):
        return (x-8)/16
    if __name__=='__main__':
    
        # x_train,x_test,y_train,y_test=mnist.train.images,mnist.test.images,mnist.train.labels,mnist.test.labels
        # linear = mlm(len(x_train[1]))
        # linear.train(x_train,y_train,x_test,y_test)
        digit=load_digits()
        x_train,x_test,y_train,y_test=train_test_split(digit.data,digit.target,test_size=0.5)
        y_lrm_train=one_hot(y_train.reshape(1,-1).tolist()[0],10)
        y_lrm_test=one_hot(y_test.reshape(1,-1).tolist()[0],10)
        x_train=normal(x_train)
        x_test=normal(x_test)
        linear=mlm(x_train.shape[1])
        linear.train(x_train,y_lrm_train,x_test,y_lrm_test)
    View Code

    注释掉的是在mnist训练集上的训练。可以看到我对digit数据集做了两个预处理:

    将target转换成one-hot:

        b = tf.one_hot(labels, class_num, 1, 0)
        with tf.Session() as sess:
            return sess.run(b)

    调用tensorflow的one_hot方法。传入的参数是(原标签,分类数,active值,negtive值)

    以这个数据集为例,每张图片是8*8的小图片,也就是有64个特征值,标签是图片对应的数字,即0 1 2 3.。。。

    所以one_hot(y,10,1,0)之后:

    1===》[0 1 0 0 0 0 0 0 0 0]

    2===》[0 0 1 0 0 0 0 0 0 0]

    。。。。。

    这样我们就可以计算交叉熵了。对应分类问题,一般都是将结果表示为one-hot的向量。

    第二个预处理是去掉颜色信息:

    return (x-8)/16

    直接简单粗暴: [x-(max-min)]/max

    由于我知道最小值是0,最大值是16,所以直接套数上去了。

    最后是部分运行结果:

    setp 0,test_loss 567.181641
    setp 1,test_loss 514.701660
    setp 2,test_loss 476.468811
    setp 3,test_loss 465.000031
    setp 4,test_loss 495.855927
    setp 5,test_loss 439.806610
    setp 6,test_loss 381.180908

    setp 2995,test_loss 16.674290
    setp 2996,test_loss 17.192608
    setp 2997,test_loss 14.386111
    setp 2998,test_loss 12.961364
    setp 2999,test_loss 14.622895
    0.93770856
    
    

    可以看到后面的训练损失值一值在抖动。不知道是为什么。

  • 相关阅读:
    JavaScript常用函数和方法
    Django中csrf错误
    LVS+Keepalived负载均衡配置
    CSP-S2019 游记
    三角函数公式整理
    LGOJP3193 [HNOI2008]GT考试
    BZOJ3790. 神奇项链
    BZOJ4241: 历史研究
    LGOJP2051 [AHOI2009]中国象棋
    AT2000 Leftmost Ball
  • 原文地址:https://www.cnblogs.com/superxuezhazha/p/9534085.html
Copyright © 2020-2023  润新知