使用TensorFlow实现线性回归预测需要使用到numpy,所以在实现线性回归预测之前,先介绍需要使用到的相关的numpy函数。

一、numpy相关函数介绍

介绍一个numpy的api查看网站http://devdocs.io/numpy~1.11/

np.random.rand()创建一个向量,参数决定产生向量的维数以及行和列的大小

一个参数的时候,产生的是一个行向量,参数的大小决定向量的列数

x = np.random.rand(3)
[0.81982865  0.82531022  0.44399218]


两个参数的时候,产生的是一个二维向量,参数的大小决定向量的行和列,第一个参数决定行数,第二个参数决定列数,下面的这个和上面的是不一样的,多了一对[]


x = np.random.rand(1,3)
[[0.67355041  0.17038178  0.80768854]]


三个参数的时候,产生的是一个三维向量,第一个参数决定的是二维向量的大小,第二个参数决定的是二维向量的行数,第三个参数决定的是二维向量的列数,以此类推rand函数有四个、五个参数....


x = np.random.rand(2,2,3)
[
   [[0.20185301  0.29129893  0.91699936]
    [0.80844255  0.24154308  0.65849662]]

   [[0.53940148  0.83237024  0.7157533]
    [0.07668698  0.95970214  0.00301952]]
]

np.float16()函数,半精度16位,5位指数(小数的整数),10位小数,还有一位符号位,整数部分超过位数就会出现inf

x = 12345.123456789
    x1 = np.float16(x)
    print(x1)# 12344.0
    x = 123456.123456789
    x1 = np.float16(x)
    print(x1)#inf

下面你会看到一个很有趣的现象,细心的同学应该能发现小数的位数会随,整数的位数变化

a = 0.123456789
    af = np.float16(a)
    print(af)#0.12347
    
    b = 1.23456789
    bf = np.float16(b)
    print(bf)#1.2344
    
    c = 12.3456789
    cf = np.float16(c)
    print(cf)#12.344
    
    d = 123.456789
    df = np.float16(d)
    print(df)#123.44
    
    e = 1234.56789
    ef = np.float16(e)
    print(ef)#1235.0


还有一个有趣的现象,有numpy的rand函数产生的小数,再经过float16之后小数的位数居然没有发生变化

x = np.random.rand(1,1)
    print(x)#[[ 0.20712529]]
    xf = np.float16(x)
    print(xf)#[[ 0.20715332]]


np.float32()函数,单精度32位,8位指数(小数的整数),23位小数

np.float64()函数,双精度64位,11位指数(小数的整数),52位小数

如果,想要深究为什么会有上面的情况,需要了解计算机小数的存储和python的相关设计,关于计算机小数的存储我推荐一篇博客

np.dot(a,b,out=None)函数,对于二维数组而言就是矩阵的乘法,对于一维数组而言就是相乘再求和,它也可以计算复数直接的乘法,也可以计算N维数组。

1、当a和b都是一维数组时,就是求数组之间的相乘之后再求和


x1 = [1,2,3]
    x2 = [4,5,6]
    y = np.dot(x1,x2)#1*4+2*5+3*6=32
    print(y)#32


2、当a和b是二维数组的时,是矩阵之间的乘法,需要注意的是矩阵之间的乘法np.dot(x1,x2)时,矩阵x1的列数要和x2的行数相等,不然就会报错,如果x2 = [[4,5]]时,就会报ValueError: shapes (2,2) and (1,2) not aligned: 2 (dim 1) != 1 (dim 0),还需要注意的时候矩阵的左乘和右乘是有区别的,即np.dot(x1,x2) != np.dot(x2,x1),除非x1 == x2的时候,下面简单用一个图表示一下矩阵点乘的过程,可能画的不是很好看,意思就是这样(行乘列求和)

tensorflow 使用模型文件进行预测 tensorflow做数据预测_数据


x1 = [[1,2],[3,4]]
    x2 = [[4],[5]]
    y = np.dot(x1,x2)
    print(y)
    '''
    [[14]
    [32]]
    '''


3、当a和b是多维数组的时,x1和x2都是三维数组的时候,把x1和x2之间的乘法拆分成了四个二维矩阵之间的乘法就是,[[1,2],[3,4]]分别和[[2,3],[2,4]]和[[2,5],[2,6]]两个矩阵的乘法以及[[1,4],[1,5]]分别和[[2,3],[2,4]]和[[2,5],[2,6]]两个矩阵的乘法,将最后的结果进行整合就可以得到y,需要注意的是x1和x2的shape都是(2,2,2)而y的shape是(2,2,2,2)


x1 = [[[1,2],[1,3]],[[1,4],[1,5]]]
    x2 = [[[2,3],[2,4]],[[2,5],[2,6]]]
    y = np.dot(x1,x2)
    print(y)
    '''
    [
     [
      [[ 6 11][ 6 17]]
      [[ 8 15][ 8 23]]
     ]
     [
     [[10 19][10 29]]
     [[12 23][12 35]]]
    ]
    '''


当a和b是多维数组的时候,这种情况需要结合上面的结果才能看懂,不然就会一脸懵逼,根本不知道怎么算出来的。[0,1,1]参数的意思是,上面的y是一个四维素组,所以下面[0,1,1]里面参数的个数最大为4,[0,1,1]中第一个参数0代表的是第一个三维数组即

[ [[6 11][6 17]]  [[8 15][8 23]] ],第二个参数1代表的是这个三维数组中的第二个二维数组[[8 15][8 23]],第三个参数的1代表的就是这个二维数组中的第二个一维数组[8 23]也就是最终的结果。

x1 = [[[1,2],[1,3]],[[1,4],[1,5]]]
    x2 = [[[2,3],[2,4]],[[2,5],[2,6]]]
    y = np.dot(x1,x2)[0,1,1]
    print(y)  #[ 8 23]


二、线性回归模型的实现


在使用TensorFlow实现一个线性模型之前,需要知道在使用机器学习来实现一个线性模型究竟是如何做到的?

其实,所谓的机器学习就是通过一堆大量的数据(数据相对于人的经验),从数据中寻找规律。线性函数y = w * x +b,对于线性模型就是通过数据的特征,来求出参数w和b,也许你会说这不是很简单嘛,给我两个点,不就能求出来了吗。对的,从数学的角度来说,这个答案的确无懈可击。但是,从工业生产的角度来说,并不是这样的,因为不可能保证所有的数据都满足同一个线性函数,更有甚者,你根本不能保证这些数据就一定是满足线性函数,有可能它们本来就是非线性的。所以,我们就不能这样来求参数w和b。在机器学习中,我们将对参数w和b的求解转换成了最优解的求解问题,就是保证我们求出来的模型计算出来的y和实际的y的差距是最小的,通过(1/2)*(实际的y-模型计算的y)^2之和最小,通常用的最优解求解方法是随机梯度下降,这里我就不详细介绍了,网上的相关资料也非常的多。

1、TensorFlow实现线性回归模型



import tensorflow as tf

if __name__ == "__main__":
    #初始化线性模型参数w和b
    w = tf.Variable([.0])
    b = tf.Variable([.0])
    #定义线性模型的输入
    x = tf.placeholder(tf.float32)
    #定义线性模型的表达式
    liner_model = w * x + b
    #初始化通过Variable方法定义的变量
    init = tf.global_variables_initializer()
    session = tf.Session()
    session.run(init)
    #定义线性模型的输出
    y = tf.placeholder(tf.float32)
    #定义线性模型的损失函数
    squared_deltas = tf.square(liner_model - y)
    #求模型损失值的和
    loss = tf.reduce_sum(squared_deltas)
    #定义使用梯度下降算法优化算法,设置下降的步长为0.01
    optimizer = tf.train.GradientDescentOptimizer(0.01)
    #最小化模型损失值的和
    train = optimizer.minimize(loss)
    #通过迭代来最小化损失值求参数w和b
    for i in range(1000):
        #每迭代一次都使损失值往最小的方向靠近
        # w = w + 0.01*(liner_model-y)*x
        # b = b + 0.01*(liner_model-y)
        session.run(train,{x:[1,2,3,4],y:[0,-1,-2,-3]})
    print(session.run([w,b]))
    #[array([-0.99999768], dtype=float32), array([ 0.99999309], dtype=float32)]

通过输入的x:[1,2,3,4]和输出的y:[0,-1,-2,-3]我们可以计算出参数w和b的值应该为1和-1,通过TensorFlow最小化损失函数的方法求出来的w和b的值分别为-0.99999768和0.99999309,已经和真实模型的参数非常接近了。通过TensorFlow提供的,tf.assign(w,[-1.])方法来修改使用tf.Variable(w)定义变量的值。


2、通过TensorFlow提供的estimator来实现一个线性模型


estimator是TensorFlow一个比较高级的库,它能够简化机器学习的结构。它的使用主要包括三个部分,训练数据的循环、评价的循环、数据的管理,estimator已经定义好了许多的模块。


import tensorflow as tf
#通常使用numpy来加载、操作和预处理数据
import numpy as np

if __name__ == "__main__":
    #声明线性模型的特征(x),x为线性模型的输入也就是模型的特征,它是一个一维的数据,所以shape=[1]
    feature_columns = [tf.feature_column.numeric_column("x",shape=[1])]
    #给estimator提供特征
    estimator = tf.estimator.LinearRegressor(feature_columns=feature_columns)
    #通过numpy来定义训练数据和评价数据
    x_train = np.array([1.,2.,3.,4.])
    y_train = np.array([0.,-1.,-2.,-3.])
    x_eval = np.array([2.,5.,8.,1.])
    y_eval = np.array([-1.01,-4.1,-7,0.])
    #设置数据的相关参数,{"x":x_train}为输入的数据,y_train为x对应的值,batch_size为迭代一次数据的大小,num_epochs迭代的次数
    # shuffle为数据是否打乱
    input_fn = tf.estimator.inputs.numpy_input_fn({"x":x_train},y_train,batch_size=4,num_epochs=None,shuffle=True)
    train_input_fn = tf.estimator.inputs.numpy_input_fn({"x":x_train},y_train,batch_size=4,num_epochs=1000,shuffle=False)
    eval_input_fn = tf.estimator.inputs.numpy_input_fn({"x":x_eval},y_eval,batch_size=4,num_epochs=1000,shuffle=False)
    #通过estimator来训练数据,steps为迭代的次数
    estimator.train(input_fn=input_fn,steps=1000)
    #评估模型的好坏,通过损失值(loss),约接近0表示越好
    train_metrics = estimator.evaluate(input_fn=train_input_fn)
    eval_metrics = estimator.evaluate(input_fn=eval_input_fn)
    print("train metrics:%r" %train_metrics)
    #train metrics:{'average_loss': 6.6502416e-08, 'loss': 2.6600966e-07, 'global_step': 1000}
    print("eval metrics:%r"%eval_metrics)
    #eval metrics:{'average_loss': 0.0025486231, 'loss': 0.010194493, 'global_step': 1000}


3、通过自定义一个estimator来训练一个线性模型


import tensorflow as tf
import numpy as np

#声明一个列表用来存储特征
def model_fn(features,labels,mode):
    #构建一个线性模型和预测值
    w = tf.get_variable("w",[1],dtype=tf.float64)
    b = tf.get_variable("b",[1],dtype=tf.float64)
    y = w * features['x'] + b
    #计算损失值
    loss = tf.reduce_sum(tf.square(y - labels))
    #训练
    global_step = tf.train.get_global_step()
    optimizer = tf.train.GradientDescentOptimizer(0.01)
    train = tf.group(optimizer.minimize(loss),tf.assign_add(global_step,1))
    return tf.estimator.EstimatorSpec(mode = mode,predictions=y,loss=loss,train_op=train)

if __name__ == "__main__":
    #使用自定义的estimator
    estimator = tf.estimator.Estimator(model_fn=model_fn)
    #定义数据
    x_train = np.array([1.,2.,3.,4.])
    y_train = np.array([0.,-1.,-2.,-3.])
    x_eval = np.array([2.,5.,8.,1.])
    y_eval = np.array([-1.01,-4.1,-7,0.])
    input_fn = tf.estimator.inputs.numpy_input_fn({"x":x_train},y_train,batch_size=4,num_epochs=None,shuffle=True)
    train_input_fn = tf.estimator.inputs.numpy_input_fn({"x":x_train},y_train,batch_size=4,num_epochs=1000,shuffle=False)
    eval_input_fn = tf.estimator.inputs.numpy_input_fn({"x":x_eval},y_eval,batch_size=4,num_epochs=1000,shuffle=False)
    #训练模型
    estimator.train(input_fn=input_fn,steps=1000)
    #评估模型
    train_metrics = estimator.evaluate(input_fn=train_input_fn)
    eval_metrics = estimator.evaluate(input_fn=eval_input_fn)
    print("trian metrics:%r"%train_metrics)
    #trian metrics:{'loss': 1.3258775e-11, 'global_step': 1000}
    print("eval metrics:%r"%eval_metrics)
    #eval metrics:{'loss': 0.010100389, 'global_step': 1000}