您的位置:首页 > 编程语言

4.2 模型之母:简单线性回归的代码实现学习笔记

2020-06-07 05:55 13 查看

1.简单线性回归算法的实现

构造一组数据,然后画图

import numpy as np
import matplotlib.pyplot as plt

x = np.array([1.,2.,3.,4.,5.])
y = np.array([1.,3.,2.,3.,5,])

plt.scatter(x,y)
plt.axis([0,6,0,6])
[0, 6, 0, 6]

根据样本真实值,来进行预测。
假设线性关系为:f(x)=ax+bf(x)=ax+bf(x)=ax+b 这根直线,然后再根据最小二乘法算a、b的值。
假设为二次函数:f(x)=ax2+bx+cf(x)=ax^2+bx+cf(x)=ax2+bx+c。可以通过最小二乘法算出a、b、c。
实际上,同一组数据,选择不同的f(x),即模型,通过最小二乘法可以得到不一样的拟合曲线。不同的数据,更可以选择不同的函数,通过最小二乘法可以得到不一样的拟合曲线。

下面回到简单线性回归,用代码计算a、b:

# 首先要计算x和y的均值
x_mean = np.mean(x)
y_mean = np.mean(y)

# a的分子num、分母d
num = 0.0
d = 0.0
for x_i,y_i in zip(x,y):   # zip函数打包成[(x_i,y_i)...]的形式
num = num + (x_i - x_mean) * (y_i - y_mean)
d = d + (x_i - x_mean) ** 2
a = num / d
b = y_mean - a * x_mean

在求出a、b之后,可以计算出y的预测值,首先绘制模型直线:

y_hat = a * x + b

plt.scatter(x,y)    # 绘制散点图
plt.plot(x,y_hat,color='r')    # 绘制直线
plt.axis([0,6,0,6])
[0, 6, 0, 6]

然后进行预测:

x_predict = 6
y_predict = a * x_predict + b
print(y_predict)
5.2

2.向量化运算

在计算参数a时,我们发现有这样一个步骤:向量w和向量v,每个向量的对应项,相乘再相加。其实这就是两个向量“点乘”

这样我们就可以使用numpy中的dot运算,非常快速地进行向量化运算。

总的来说:

向量化是非常常用的加速计算的方式,特别适合深度学习等需要训练大数据的领域。

对于 y = wx + b, 若 w, x都是向量,那么,可以用两种方式来计算,第一是for循环:

y = 0
for i in range(n):
y += w[i]*x[i]
y += b

另一种方法就是用向量化的方式实现:

y = np.dot(w,x) + b

二者计算速度相差几百倍,测试结果如下:

import numpy as np
import time

a = np.random.rand(1000000)
b = np.random.rand(1000000)

tic = time.time()
c = np.dot(a, b)
toc = time.time()
print("c: %f" % c)
print("vectorized version:" + str(1000*(toc-tic)) + "ms")

c = 0
tic = time.time()
for i in range(1000000):
c += a[i] * b[i]
toc = time.time()
print("c: %f" % c)
print("for loop:" + str(1000*(toc-tic)) + "ms")
c: 249811.646073
vectorized version:2.9993057250976562ms
c: 249811.646073
for loop:361.07492446899414ms

对于独立的样本,用for循环串行计算的效率远远低于向量化后,用矩阵方式并行计算的效率。因此:

只要有其他可能,就不要使用显示for循环。

3.自实现的工程文件

3.1 代码

创建一个SimpleLinearRegression.py,实现自己的工程文件并调用

import numpy as np

class SimpleLinearRegression:
def __init__(self):
"""模型初始化函数"""
self.a_ = None
self.b_ = None

def fit(self, x_train, y_train):
"""根据训练数据集x_train,y_train训练模型"""
assert x_train.ndim ==1, \
"简单线性回归模型仅能够处理一维特征向量"
assert len(x_train) == len(y_train), \
"特征向量的长度和标签的长度相同"
x_mean = np.mean(x_train)
y_mean = np.mean(y_train)
num = (x_train - x_mean).dot(y_train - y_mean)  # 分子
d = (x_train - x_mean).dot(x_train - x_mean)    # 分母
self.a_ = num / d
self.b_ = y_mean - self.a_ * x_mean

return self

def predict(self, x_predict):
"""给定待预测数据集x_predict,返回表示x_predict的结果向量"""
assert x_predict.ndim == 1, \
"简单线性回归模型仅能够处理一维特征向量"
assert self.a_ is not None and self.b_ is not None, \
"先训练之后才能预测"
return np.array([self._predict(x) for x in x_predict])

def _predict(self, x_single):
"""给定单个待预测数据x_single,返回x_single的预测结果值"""
return self.a_ * x_single + self.b_

def __repr__(self):
"""返回一个可以用来表示对象的可打印字符串"""
return "SimpleLinearRegression()"

3.2 调用

首先创建一组数据,然后生成SimpleLinearRegression()的对象reg1,然后调用一下

from SimpleLinearRegression import SimpleLinearRegression

x = np.array([1.,2.,3.,4.,5.])
y = np.array([1.,3.,2.,3.,5,])
x_predict = np.array([6])
reg = SimpleLinearRegression()reg.fit(x,y)
SimpleLinearRegression()
reg.predict(x_predict)
array([5.2])
reg.a_
0.8
reg.b_
0.39999999999999947
y_hat = reg.predict(x)

plt.scatter(x,y)
plt.plot(x,y_hat,color='r')
plt.axis([0,6,0,6])
plt.show()

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐