线性回归:
简单案例 y = w*x + b w: 权重 b: 偏置
w,b 都是向量
y: 标签
x: 特征
"""
简单线性回归实例
y = 3*x + 2
人工制造数据集:
随机生成一个近似采样随机分布,使得w=3.0, b=2, 并加入一个噪声,噪声的最大振幅为0.4
学习目标: w =3 , b =2
"""
使用了4种方法:思路都是一样,实现条件不同。
way 1: 概率估计 :w , b (完全按照书上堆公式,最大似然估计法)
way 2: 机器学习:公式推导,自己写底层函数,求导,更新w,b
way 3 : 机器学习: 求导,借助 梯度带 tf.GradientTape 求导 gradient
way 4 : 机器学习 : tf.optimizers 优化器更新w,b 求导tf.GradientTape)
把概率推导放在最后,其实挺简单,大致思路:最大似然估计->求偏导-> 解方程。
本机环境:编写环境(Jupyter)
1:数学公式推导 :估计未知参数: a(对应公式中的 b), b (w)
"""
简单线性回归实例
y = 3*x + 2
人工制造数据集:
随机生成一个近似采样随机分布,使得w=3.0, b=2, 并加入一个噪声,噪声的最大振幅为0.4
"""
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from time import time
# 设置随机数种子
np.random.seed(10)
# np.linspace 生成等差数列在-(-1,5)之间 100个点
x_data = np.linspace(-1,1,100)
# *x_data.shape 将转成数字 标准正态分布。加入噪音0.4
y_data = 3*x_data +2.0+np.random.randn(*x_data.shape)*0.4
n = x_data.shape[0] # 数据集的总数据个数
# 一元线性回归的估计:公式具体参照《概率论与数理统计》 第4版 浙江大学p 248 页
start_Time= time()
s_xx = np.sum(np.square(x_data)) -(1/n)*np.square(np.sum(x_data))
s_yy = np.sum(np.square(y_data)) -(1/n)*np.square(np.sum(y_data))
s_xy = np.sum(x_data*y_data) - (1/n)*np.sum(x_data)*np.sum(y_data)
b = s_xy / s_xx
a = (1/n)*np.sum(y_data)-( 1/n*np.sum(x_data) )*b
duration = time() -start_Time
print("Train Finished take %5f "%(duration))
print("根据公式可以估计 a,b 的值:")
print("a =%f b=%f" %(a,b))
# 绘制图
#画出 随机生成数据集的散点图
plt.plot(x_data, y_data, 'go', label='Original data')
# 我们想要学习到的线性函数 y = 3*x + 2
plt.plot(x_data,3*x_data+2.0,color='black',label='aim: Linear')
# 数学估计:回归直线
plt.plot(x_data, a+b*x_data, color='r',label='studing:Linear regression')
plt.legend()
plt.show()
# 利用模型进行预测
x_test = 3.14
predict = b * x_test +a
target = 3*x_test + 2.0
print('当x_test = 3.14 时:预测值:%f 目标值:%f'%(predict,target))
这里的 a: ->b b->w
2: 机器学习:w ,b 自己写函数
import numpy as np
import matplotlib.pyplot as plt
from time import time
### 人工生成数据集
# np.linspace 生成等差数列在-(-1,1)之间 100个点
x_data = np.linspace(-1,1,20)
# *x_data.shape 将转成数字 标准正态分布。
y_data = 3*x_data +2.0+np.random.randn(*x_data.shape)*0.4
#plt.plot(x_data, y_data, 'go', label='Original data') #画出数据集的图像
data_num = x_data.shape[0] # 获取数据集的大小
x0= np.ones((data_num, 1)) #扩充矩阵 x0一列都等于1,便于矩阵运算
x=x_data.reshape((data_num,1))
x =np.hstack((x0,x)) #按照列堆叠形成数组,其实就是 m*[x0,x1]样本数据
y=y_data.reshape((data_num,1))
### 定义损失函数
def loss_Function(theta,x,y,m):
"""
theta: [ [θ1],[θ2] ] 待求参数 shape : 2*1 θ1 ->a θ2 ->b
x : 数据集 m *[x0,x1] shape: m *2 x0 这一列全为1
y : 标签值 shape: m *1
m : 数据集个数
"""
# 均方差
Subtraction =np.dot(x,theta) -y
square = 1/(2*m)*np.dot(np.transpose(Subtraction) ,Subtraction)
return square
###定义损失函数对应的梯度函数
def gradinet_Function(theta,x,y,m):
"""
theta: [ [θ1],[θ2] ] 待求参数 shape : 2*1
x : 数据集 m *[x0,x1] shape: m *2
y : 标签值 shape: m *1
m : 数据集个数
"""
#参照矩阵求导公式
diff = np.dot(x,theta)-y
square =1/m*np.dot(np.transpose(x),diff)
return square
### 超参数
learning_rate = 0.01
traing_epochs = 3000
### 训练参数初始化
theta = np.array([1, 1]).reshape(2, 1) # 初始化theta ,默认为 1
loss_history = [] # 保存损失
### 开始训练
start_Time= time()
for epoch in range(traing_epochs+1):
gradient = gradinet_Function(theta,x,y,data_num) #计算梯度
theta = theta -learning_rate*gradient #更新theta
loss =loss_Function(theta,x,y,data_num)
loss_history.append(loss[0])
if epoch %1000 ==0:
print("第%d轮 loss= %f a= %0.6f b=%0.6f"%(epoch,loss,theta[0],theta[1]))
duration = time() -start_Time
print("Train Finished take %5f "%(duration))
print("最终得到 a= %0.6f b=%0.6f"%(theta[0],theta[1]))
###数据可视化
def plot_(theta,x,y):
ax = plt.subplot(111)
ax.scatter(x, y, s=10, marker="s",color='black')
plt.xlabel("X")
plt.ylabel("Y")
#目标直线
plt.plot(x_data,3*x_data+2.0, linewidth = '1',color='red',label='aim: Linear',marker='o')
#学习直线
y1 = theta[0] + theta[1]*x
ax.plot(x, y1,linewidth = '1',color='yellow',label="sty:Linear")
plt.legend(loc='upper left')
plt.show()
plot_(theta,x[:,1],y)
plt.plot(loss_history)
3 机器学习:梯度带 tf.GradientTape 求导 gradient
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from time import time
# 设置随机数种子
np.random.seed(10)
# np.linspace 生成等差数列在-(-1,1)之间 100个点
x_data = np.linspace(-1,1,100)
# *x_data.shape 将转成数字 标准正态分布。加入噪音0.4
y_data = 3*x_data +2.0+np.random.randn(*x_data.shape)*0.4
#定义模型函数
def model(x,w,b):
return w*x +b
# 定义MSE损失函数
def loss_Squared(y_estimate,y,n):
"""
y_estimate : 是估计值 向量vector
y: 真实值 label
n: 数据集数据总数
loss = (y_estimate- y)^2 * 1/(2*n)
"""
result = tf.reduce_sum(tf.pow(y_estimate - y,2) )
return result
# 随机选择样本函数
def data_iter(features, labels ,mini_batch):
"""
数据迭代函数
Args:
- features: 特征矩阵 nxd 维
- labels: 样本,nx1 维
- mini_batch: 每次抽取的样本数
"""
index =list(range(len(features)))
np.random.shuffle(index) #打乱顺序
for i in range(0,len(index),mini_batch): # 增量 mini_batch
j = np.array(index[i:min(i+mini_batch,len(features))])
yield features[j] ,labels[j] # 相当于一个断点 ,产生一个mini_batch小样本
# 参数更新函数
def update_sgd(params, learning_rate,loss):
'''
计算梯度,并更新模型参数
Args:
- params: 模型参数,本例中为 [w, b]
- learning_rate: 学习率 learning rate
'''
for param in params: # 依次更新w ,b
param.assign_sub(learning_rate * tape.gradient(loss, param))
#tensorflow 变量的生明 是tf.Variable 保存和更新参数
# 变量的初始值通常是随机数,常数,或者其他变量得到的
# 训练参数
w = tf.Variable(np.random.rand(),dtype=tf.float64)
b = tf.Variable(np.random.rand(),dtype=tf.float64)
#超参数
traing_epoch = 300 #训练轮数
learning_rate = 0.02
mini_batch = 10 #每次抽取的样本数
loss_history = []
# 开始训练
start_Time= time()
for i in range(traing_epoch+1):
for x,y in data_iter(x_data,y_data,mini_batch):
# 在内存中记录梯度过程
with tf.GradientTape(persistent=True) as tape :
tape.watch([w,b])
y_estim = model(x,w,b)
loss = loss_Squared(y_estim,y,mini_batch)
loss_history.append(loss)
#计算梯度,更新参数
update_sgd([w,b],learning_rate,loss)
#计算本次迭代的总误差
train_loss = loss_Squared(model(x_data,w,b),y_data,len(x_data))
if i%50 ==0:
print('epoch %d : loss: %f w:%f b:%f ' % (i , tf.reduce_mean(train_loss),w.numpy(),b.numpy()))
duration =time() -start_Time
print("Train Finished take %5f "%(duration))
print('最后的结果 : loss: %f w:%f b:%f ' % ( tf.reduce_mean(train_loss),w.numpy(),b.numpy()))
# 利用模型进行预测
x_test = 3.14
predict = model(w,x_test,b)
target = 3*x_test + 2.0
print('当x_test = 3.14 时:预测值:%f 目标值:%f'%(predict,target))
###数据可视化
def plot_(w,b):
ax = plt.subplot(111)
#画出 随机生成数据集的散点图
ax.plot(x_data, y_data, 'go', label='Original data')
plt.xlabel("X")
plt.ylabel("Y")
#目标直线
plt.plot(x_data,3*x_data+2.0, linewidth = '1',color='red',label='aim: Linear',marker='o')
#学习直线
y_prediction = np.array(w * x_data + b)
ax.plot(x_data, y_prediction,linewidth = '1',color='yellow',label="sty:Linear")
plt.legend(loc='upper left')
plt.show()
plot_(w,b)
plt.plot(loss_history)
4:借用tensorlfow 实现
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import random
from time import time
# np.linspace 生成等差数列在-(-1,1)之间 100个点
x_data = np.linspace(-1,1,10)
# *x_data.shape 将转成数字 标准正态分布。
y_data = 3*x_data +2.0+np.random.randn(*x_data.shape)*0.4
data_num = x_data.shape[0]
# arguments :
learning_rate = 0.01
training_epoch=1500
loss_history = []
# 随机初始化权重,偏置
w = tf.Variable(0.0,name='weights')
b = tf.Variable(np.random.randn(),name='bias')
# 线性回归 w*x + b
def linear_regression(x,w,b):
return tf.multiply(w,x) + b
# 损失函数
def mean_square(y_pred ,y_true):
return tf.reduce_sum(tf.pow(y_pred-y_true,2)) /(2.0*data_num)
# 梯度下降
optimizer = tf.optimizers.SGD(learning_rate)
#训练参数
start_Time =time()
for epoch in range(training_epoch+1):
with tf.GradientTape() as tape:
tape.watch([w,b])
pred = linear_regression(x_data,w,b)
loss = mean_square(pred,y_data)
loss_history.append(loss)
# 计算梯度
gradients = tape.gradient(loss,[w,b])
optimizer.apply_gradients(zip(gradients,[w,b])) #自动更新 w b
if epoch % 200 ==0:
print('epoch: %i ,loss: %f, w: %f b=%f ' %(epoch,loss,w.numpy(),b.numpy()))
duration =time() -start_Time
print("Train Finished take %5f "%(duration))
print('最后的结果: w: %f b: %f ' % (w.numpy(),b.numpy()))
# 利用模型进行预测
x_test = 3.14
predict = linear_regression(w,x_test,b)
target = 3*x_test + 2.0
print('当x_test = 3.14 时: 预测值:%f 目标值:%f'%(predict,target))
#数据可视化化
def plot_(w,b):
ax = plt.subplot(111)
#画出 随机生成数据集的散点图
ax.plot(x_data, y_data, 'go', label='Original data')
plt.xlabel("X")
plt.ylabel("Y")
#目标直线
plt.plot(x_data,3*x_data+2.0, linewidth = '1',color='red',label='aim: Linear',marker='o')
#学习直线
y_prediction = np.array(w * x_data + b)
ax.plot(x_data, y_prediction,linewidth = '1',color='yellow',label="sty:Linear")
plt.legend(loc='upper left')
plt.show()
plot_(w,b)
plt.plot(loss_history)
一元线性回归:(推导)