美文网首页我爱编程
【TensorFlow每周一练】线性回归问题

【TensorFlow每周一练】线性回归问题

作者: 安安爸Chris | 来源:发表于2018-08-08 11:28 被阅读0次

    这个例子很多教材和博客可能都已经写过了。比较常见的一个问题,就是良性肿瘤和恶心肿瘤的分类。

    我们对肿瘤做二个维度的采样,一个是病人年纪,一个是肿瘤大小

    因为没有实际数据,我们采用生成样本数据来模拟。

    def generate_samples(num, mean, cov, diff):
        X0 = np.random.multivariate_normal(mean, cov, num)
        Y0 = np.zeros(num)
    
        for ci, d in enumerate(diff):
            X1 = np.random.multivariate_normal(mean + d, cov, num)
            Y1 = (ci + 1) * np.ones(num)
    
            X0 = np.concatenate((X0, X1))
            Y0 = np.concatenate((Y0, Y1))
    
        return X0, Y0
    
    mean = np.random.randn(num_class)
    cov = np.eye(num_class)
    X, Y = generate_samples(200, mean, cov, [3])
    colors = ['r' if l == 0 else 'b' for l in Y[:]]
    plt.scatter(X[:, 0], X[:, 1], c=colors)
    plt.xlabel("age(in year)")
    plt.ylabel("size(in cm)")
    plt.show()
    

    multivariate_normal是用于生成二维正太分布的函数。具体请参考正太分布的使用
    X0是(num,2)矩阵,num是入参。2是表示了年纪和大小两个维度的参数。
    Y0是样本编号。0是第一组样本,1为第二组样本,以此类推。样本有几组是有diff参数决定的。diff是一个一维数组。数组的个数就是除0组外的样本个数。

    生成肿瘤分布样本.png

    坐标轴有负值,可以理解为以某个年纪/某个大小为参考。如果要把坐标值改为正值,可以在把mean值调整一下。

    input_dim = 2
    lab_dim = 1
    input_feature = tf.placeholder(tf.float32, [None, input_dim])
    input_labels = tf.placeholder(tf.float32, [None, lab_dim])
    
    W = tf.Variable(tf.random_normal([input_dim, lab_dim]), name="weight")
    b = tf.Variable(tf.zeros([lab_dim]), name="bias")
    
    output = tf.nn.sigmoid(tf.matmul(input_feature, W) + b)
    cross_entropy = -(input_labels * tf.log(tf.clip_by_value(output, 1e-10,1.0)) + (1 - input_labels) * tf.log(tf.clip_by_value(1 - output, 1e-10,1.0)))
    ser = tf.square(input_labels - output)
    err = tf.reduce_mean(ser)
    loss = tf.reduce_mean(cross_entropy)
    optimizer = tf.train.AdamOptimizer(0.04).minimize(loss)
    

    因为output如果过小的话,tf.log的值可能为Nan。所以使用tf.clip_by_value规避此问题。

    这里使用了信息论里的交叉熵,基本的理论知识可以百度一下。

    直接摆出公式,


    交叉熵公式.PNG

    训练方法是用AdamOptimizer。其他的也可以。

    接下来看执行部分代码,

    max_epochs = 50
    mini_batch_size = 25
    
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
    
        for epoch in range(max_epochs):
            sum_err = 0
            for i in range(np.int32(len(X) / mini_batch_size)):
                x1 = X[i * mini_batch_size:(i + 1) * mini_batch_size,:]
                y1 = np.reshape(Y[i * mini_batch_size:(i + 1) * mini_batch_size], [-1, 1])
    
                _, lossval, outputval, errval = sess.run([optimizer, loss, output, err], feed_dict={input_feature: x1, input_labels: y1})
                sum_err = sum_err + errval
    
            print("epoch:", '%04d' % (epoch + 1), "cost=", "{:.9f}".format(lossval), "err=", sum_err/mini_batch_size)
    
        x = np.linspace(0, 10, 200)
        y = -x * (sess.run(W)[0] / sess.run(W)[1]) - sess.run(b) / sess.run(W)[1]
        plt.plot(x, y, label='Fitted line')
        plt.legend()
        plt.show()
    
    

    最后生成图


    生成肿瘤分布线性回归.png

    需要注意的,如果坐标抽通过修改mean后全部改为大于0了,生成的直线可能并没有随之发生移动,导致最后可能的结果“感觉上”不正确。可以同时修改一下直线的位置,让它发生相同的“位移”。

    相关文章

      网友评论

        本文标题:【TensorFlow每周一练】线性回归问题

        本文链接:https://www.haomeiwen.com/subject/svetbftx.html