线性回归的推导与简单的一元线性回归代码实现

 

直入正题,一元线性回归就是一次函数,即y=kx+b

在线性函数中,x就是自变量,即模型需要输入的数据,y就是因变量,即我们需要预测的值

我们如何拟合一条符合数据变化趋势的曲线呢?这就要涉及误差值了,因为拟合出来的曲线能否代表数据特征,我们需要一个评判标准

曲线绝对无法完全拟合到每一个数据点上,但是我们能在这种拟合中寻找最优的那条曲线,评判依据就是误差值,什么是这里的误差值呢?

在这里我们将误差设为ee=y-kx-b

鉴于误差存在正负的波动所以我们以|e|来代表误差的大小,要求最小的误差,即求|e|的最小值

在整个训练数据集中就求:  \sum_{n=i}^n \left | e \right | 的最小值,将公式进行推导,如下

\left (\sum_{n=i}^n \left | e \right | \right)_{min} \Rightarrow \left (\sum_{n=i}^n e^2 \right)_{min} \Rightarrow \left (\sum_{n=i}^n {y_{i}-kx_i-b}}^2 \right)_{min}

令S为

S =\sum_{n=i}^n \left ( {y_{i}-kx_i-b}} \right)^2

为求S的极值,需要对k,b求偏导,并使其等于0,最后求出k,b的值用于代码的编写

\frac{\partial S}{\partial k}=2\times \sum_{i=1}^n \left ( y_i-kx_i-b \right ) \left ( -x_i \right )

\frac{\partial S}{\partial b}=2\times \sum_{i=1}^n \left ( y_i-kx_i-b \right ) \left ( -1 \right )

\Rightarrow b = \frac{\sum_{i=1}^n (y_i-kx_i)}{n}=\frac{\sum_{i=1}^n y_i-k \sum_{i=1}^{n} x_i}{n}

\Rightarrow k = \frac{n*\sum_{i=1}^n x_iy_i-\sum_{i=1}^n y_i*\sum_{i=1}^n x_i}{n*\sum_{i=1}^n x^2 - (\sum_{i=1}^n x_i)^2}

以下是代码部分,采用python语言编写:

首先生成下测试数据

import numpy as np
import matplotlib.pyplot as plt

x = np.random.uniform(-10,10,size=100)
y = .4 * x + 3 + np.random.uniform(-1,1,size=100)

f = open('dataset/simulation_data_1d.txt','w')
for i in range(0,100):
    line = str(x[i]) + ',' + str(y[i])
    f.write(line)
    f.write('\n')

plt.plot(x,y,'b.')
plt.show()

然后根据算法推导结果编写算法部分

import matplotlib.pyplot as plt
import random

data = open('dataset/simulation_data_1d.txt', 'r').read()
# print(data.split('\n'))

# 数据读取
x = []
y = []
for item in data.split('\n'):
    if item != '':
        item = item.split(',')
        x.append(float(item[0]))
        y.append(float(item[1]))


# 数据集构建
def seperateData(x, y, test_scale):
    # 将x,y进行矩阵组合
    data = []
    for _x in x:
        i = x.index(_x)
        data.append([])
        if type(_x) == 'list':
            for feature in range(len(_x)):
                data[i].append(feature)
            data[i].append(y[i])
        else:
            data[i].append(_x)
            data[i].append(y[i])

    # 切割数据集
    train = []
    test = []
    random.seed(3)
    for i in range(len(data)):
        count = random.random()
        if count > test_scale:
            train.append(data[i])
        elif count < test_scale:
            test.append(data[i])
    return train, test


train, test = seperateData(x, y, 0.2)

# 处理成能够用于模型训练的数据结构
X_train = []
Y_train = []
X_test = []
Y_test = []
for item in train:
    X_train.append(item[:-1])
    Y_train.append(item[-1])
for item in test:
    X_test.append(item[:-1])
    Y_test.append(item[-1])

Xsum = 0.0
Ysum = 0.0
XY = 0.0
X2sum = 0.0
n = len(Y_train)
# 推导的算法结果部分的实现
for i in range(n):
    Xsum += X_train[i][0]
    Ysum += Y_train[i]
    XY += X_train[i][0] * Y_train[i]
    X2sum += X_train[i][0] ** 2
k = (n * XY - Xsum * Ysum) / (n * X2sum  - Xsum ** 2)
b = (Ysum - k * Xsum) / n
print("拟合的曲线:y =",k,"* x +",b)

plt.plot(X_train, Y_train, 'b.')
plt.plot(X_test, Y_test, 'r*')
plt.xlabel("Trian_Area")
plt.ylabel("Trian_Price")

# 绘制拟合的曲线
Y = []
for item in X_test:
    Y.append(k * item[0] + b)
plt.plot(X_test, Y, 'g-')

plt.show()

总结:我jio的还口以,如有错误欢迎指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

请叫我徐先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值