TensorFlow梯度下降法求解线性回归模型

详细代码如下:

"""
        线性回归模型数学表达式:
            y=c1*x_1+...+cn*x_n+e  (1),
        e是一个服从正态分布的随机变量,即 e ~ N(u,sigma^2)
        符号约定:
        (1)假设有m个数据,第i个数据xi记为xi=(x_i1,...,x_in),对应的y值记为yi,如下:
                y1=c1*x_11+...+cn*x_1n+e1
                y2=c1*x_21+...+cn*x_2n+e2
                        ...
                ym=c1*x_m1+...+cn*x_mn+em
            ei不同于e,这里的ei是值,不是随机变量,这些值的平均值是u,方差是sigma^2
        (2)如下约定:
                Y=(y1,y2,...,ym)^T
                矩阵X=
                       x_11 x12 ... x_1n
                       x_21 x21 ... x_2n
                           ...
                       x_m1 xm1 ... x_mn
                beta=(c1,c2,...cn)^T
                E=(e1,e2...,em)^T
                符号^T表示矩阵转置
        (3)线性回归模型矩阵形式表示如下:
                Y=X*beta+E
                generate_data方法就是根据这个随机生成数据的,
                create_linear_model中省略了随机扰动项E,使用的是Y=X*beta
        (4)损失函数:
                L=(y1_pred-y1)^2 + ... + (ym_pred-ym)^2
                yi_pred表示是数据xi根据求解后的模型计算出的预测值
                代码中使用的是L/m,m是数据的个数,当数据的个数确定后,
                两种损失函数等价,求解的模型参数一样
"""

import tensorflow as tf
import numpy as np


def create_linear_model(dimension):
    """定义线性回归模型
    :param dimension: 数据的维数或者数据特征个数,比如对于数据x=(1,4,3),dimension就是3
    :return: 返回创建好的模型
    """

    # 自变量,x=(x1,...,xn),n=dimension,数据个数不确定,所以使用了None
    x = tf.placeholder(tf.float64, shape=[None, dimension], name='x')
    # 因变量,对应表达式的y
    y = tf.placeholder(tf.float64, shape=[None, 1], name='y')
    # 模型参数,对应模型中的c
    beta = tf.Variable(np.random.random([dimension, 1]))
    # 定义模型的表达式Y=X*beta
    y_pred = tf.matmul(x, beta, name='y_pred')
    # 定义损失函数(y_pred-y)^2/m
    loss = tf.reduce_mean(tf.square(y_pred - y))
    # 定义模型
    model = {'loss_function': loss,
             'independent_variable': x,
             'dependent_variable': y,
             'prediction': y_pred,
             'model_params': beta}

    return model


def gradient_descent(X, Y, model, learning_rate=0.01, max_iter=10000, tol=1.e-6):
    """
    梯度下降法
    :param x: 自变量数据
    :param y: 因变量数据
    :param model: 模型
    :param learning_rate:学习率,默认是0.01
    :param max_iter: 最大迭代次数,达到最大迭代次数,算法终止
    :param tol: 总误差,默认是0.000001,误差小于该值算法终止
    :return:
    """

    # 定义梯度下降法,并设置学习率
    method = tf.train.GradientDescentOptimizer(learning_rate=learning_rate)
    # 定义一个求解“最小化损失函数“优化问题的优化器:
    optimizer = method.minimize(model['loss_function'])

    # 收集迭代过程中变量的数据信息
    tf.summary.scalar('loss_function', model['loss_function'])
    tf.summary.histogram('params', model['model_params'])
    tf.summary.scalar('first_param', tf.reduce_mean(model['model_params'][0]))
    tf.summary.scalar('last_param', tf.reduce_mean(model['model_params'][-1]))
    summary = tf.summary.merge_all()
    # 创建信息读写器,将数据信息写入文件
    summary_writer = create_summary_writer('logs/gradient_descent')
    # 模型变量初始化
    sess = tf.Session()
    init = tf.global_variables_initializer()
    sess.run(init)
    # 梯度下降法开始迭代
    step = 0
    pre_loss = np.inf
    diff = np.inf
    while (step < max_iter) & (diff > tol):
        _, summary_info, loss = sess.run([optimizer, summary, model['loss_function']],
                                         feed_dict={model['independent_variable']: X,
                                                    model['dependent_variable']: Y})
        # 每次迭代的数据信息写入文件
        summary_writer.add_summary(summary_info, step)
        diff = abs(pre_loss - loss)
        pre_loss = loss
        step += 1
    summary_writer.close()


def generate_data(num, dimension):
    """
    随机产生模型数据,可以先阅读下create_linear_model方法中的文档注释
        例如:num=5,dimension=3
    beta= [1 2 3]
    X=
        [[0.17586156 0.1817122  0.531554  ]
         [0.93252625 0.24245416 0.21445602]
         [0.52736959 0.41516182 0.30301268]
         [0.96282288 0.89517138 0.6235028 ]
         [0.98281141 0.06380074 0.47512007]]
    E=
        [[0.50326889]
         [0.61182256]
         [0.74906335]
         [0.64430668]
         [0.77042713]]
    Y=
        [[2.63721685]
         [2.67262519]
         [3.01579462]
         [5.26798074]
         [3.30620023]]
    :param dimension: 数据维数
    :param num: 数据个数
    :return: 随机生成的数据X,Y
    """
    # 模型参数数据生成,为了生成Y,shape(1,dimension)
    beta = np.array(range(dimension)) + 1
    # 输入数据生成,shape(num, dimension)
    X = np.random.random((num, dimension))
    # 扰动项数据生成,shape(num, 1)
    E = np.random.random((num, 1))
    # 使用线性回归表达式生成y,shape(num, 1)
    Y = X.dot(beta).reshape((-1, 1)) + E

    return X, Y


def run():
    """
    程序入口
    :return:
    """
    # 随机生成数据
    num, dimension = 5, 3
    x, y = generate_data(num, dimension)
    # 定义模型
    model = create_linear_model(dimension)
    # 使用梯度下降法估计模型参数
    gradient_descent(x, y, model)


def create_summary_writer(log_path):
    """定义信息收集器
    :param log_path:
    :return:
    """
    if tf.gfile.Exists(log_path):
        tf.gfile.DeleteRecursively(log_path)
    summary_writer = tf.summary.FileWriter(log_path, graph=tf.get_default_graph())

    return summary_writer


if __name__ == '__main__':
    run()

程序成功执行后,生成一个数据信息文件,如图: 

 执行tensorboard --logdir [file_path]命令,如图:

file_path是文件所在目录,命令执行成功后,输出浏览器访问地址:http://leboop:6006

打开浏览器访问,程序在迭代过程中收集的数据信息,如图:

(1)标量信息,模型的第一个参数first_param和最后一个参数last_param,以及损失函数loss,如图:

 

(2)矩阵变量信息, 整个模型参数params,如图:

(3)TensorFlow计算图,如图: 

(4)模型参数分布图,如图:

发布了89 篇原创文章 · 获赞 79 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/L_15156024189/article/details/104829316
今日推荐