一、线性回归
1 流程
- 线性回归:
- 1 通过可视化寻找模型->
- 2 表示和推导模型->
- 表示方式使用矩阵,向量内积、点积
- 表示方式使用矩阵,向量内积、点积
- 3 模型存在误差->
- 4 计算出现误差的概率->
- 误差表达式
,误差满足高斯分布(正太分布),根据高斯概率密度函数,已知误差就可以计算出现误差的概率;若训练样本已知可以计算出现误差的概率(最大似然函数)
- 误差表达式
- 5 对模型进行优化-> 误差越小,概率越大
- 6 把误差模型应用到线性模型中->
- 7 找y=wx+b中w值->
- 8 通过numpy或sklearn实现
2 概念
训练样本:
已有的数据通过算法得出一定的规律, 已有的数据叫做已有样本,这些专门用来找规律的数据就是训练样本
,验证训练好的数据有没有正确,多少是正确的,叫测试样本
,已知样本的值,期望的得到数据值叫做标签数据。
样本的作用就是用来预测
和分类
- 线性回归--最小二乘法
3 常用函数
- mat ---> https://blog.csdn.net/qq_38150441/article/details/79893747
- linspace ---> https://www.cnblogs.com/antflow/p/7220798.html
- 在指定的间隔内返回均匀间隔的数字
- zeros ---> https://blog.csdn.net/qq_36621927/article/details/79763585
- 返回来一个给定形状和类型的用0填充的数组,,,
- endpoint : bool, optiona,如果是真,则一定包括stop,如果为False,一定不会有stop
- 返回来一个给定形状和类型的用0填充的数组,,,
- reshape ---> 转换形状 url同matmul
- np.reshape(x, (a, b)) x:原矩阵,(a, b):要转变的形状
- 如果reshape的第一个参数是None或者-1,表明行数是不确定的
- np.reshape(x, (a, b)) x:原矩阵,(a, b):要转变的形状
- matmul ---> https://blog.csdn.net/alwaysyxl/article/details/83050137
- 矩阵相乘 numpy.matmul(a, b, out=None),貌似和np.dot很像(multiply、*)
- np.dot与np.matmul的区别
- 1.二者都是矩阵乘法。
- 2.np.matmul中禁止矩阵与标量的乘法。
- 3.在矢量乘矢量的內积运算中,np.matmul与np.dot没有区别。
- 4.np.matmul中,多维的矩阵,将前n-2维视为后2维的元素后,进行乘法运算。
- np.dot与np.matmul的区别
- 矩阵相乘 numpy.matmul(a, b, out=None),貌似和np.dot很像(multiply、*)
- x.I --> x的逆矩阵 --> url同mat
- x.T --> x的转置矩阵 --> url同mat
4 绘制正态分布图
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure('标准正态概率函数', figsize=(6, 4))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
n = lambda x: (1.0 / np.sqrt(np.pi * 2.0)) * np.exp(- x**2 / 2.0)
x = np.linspace(-5, 5, 100)
y = n(x)
ax.set_ylim(0, 0.5)
ax.plot(x, y, color='g')
y_0 = n(2)
y_001 = n(0.001)
ax.scatter(2, y_0, c='b', marker='>')
ax.scatter(0.001, y_001, c='b', marker='8', s=49) # marker='>'
fig.show(warn=False)
# plt.show()

(100, 1)
# list=['1','2','3','a','b','c']
list=[1,2,3,'a','b','c']
l = str(list)
print(l)
# print(':'.join(list))
[1, 2, 3, 'a', 'b', 'c']
5 numpy实现
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import numpy.linalg as la
# 1.加载
x_data = np.loadtxt('ex2x.dat') # 年龄
y_data = np.loadtxt('ex2y.dat') # 身高
# 对x和y的数据处理,每个数据加1,对应权重
x = np.zeros(shape=(x_data.shape[0], 2), dtype=np.float) # 把数组转成矩阵
"""
[[0. 0.]
[0. 0.]
.....
[0. 0.]]
"""
x[:, 0] = x_data
x[:, 1] = 1
y = y_data.reshape(y_data.shape[0], 1)
# print(y)
# 2.算法,求w
s1 = np.matmul(x.T, x)
s2 = la.inv(s1) # 矩阵可能没有逆矩阵
s3 = np.matmul(s2, x.T)
s4 = np.matmul(s3, y) # 上面斜率 鞋面截距
# 3.可视化效果(样本点,回归直线)
# 绘制样本点
fig = plt.figure('年龄与身高', figsize=(6, 4))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.set_xlim(0, 9)
ax.set_ylim(0.3, 1.5)
ax.scatter(x_data, y_data, c='g', marker='.')
# 绘制直线
x_pos = np.linspace(1.5, 8.5, 100, dtype=np.float) # 在指定的间隔内返回均匀间隔的数字
x_pra = np.zeros((x_pos.shape[0], 2), dtype=np.float)
x_pra[:, 0] = x_pos
x_pra[:, 1] = 1
# 计算直线的y坐标
w = s4
y_pra = np.matmul(x_pra, w)
# y_spa 做一个形状变换
ax.plot(x_pos, y_pra, color=(1, 0, 0, 1), label='线性回归')
ax.legend()
fig.show(warn=False)

- 下面测试和验证细节、矩阵计算
##########################################################
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import numpy.linalg as la
# 1.加载
x_data = np.loadtxt('ex2x.dat')
y_data = np.loadtxt('ex2y.dat')
# 对x和y的数据处理,每个数据加1,对应权重
x = np.zeros(shape=(x_data.shape[0], 2), dtype=np.float)
x[:, 0] = x_data
x[:, 1] = 1
y = y_data.reshape(y_data.shape[0], 1)
# print(y) #50个 50行 1列
# 2.算法,求w
xt = x.T
s1 = np.matmul(xt, x)
s2 = la.inv(s1) # # 矩阵可能没有逆矩阵
# print(s2)
s3 = np.matmul(s2, xt)
# print(s3) #[[50个][50个]] 2行 50列
w = np.matmul(s3, y) # # 上面斜率 下面截距
# print(w) #[[1个][1个]] 2行 1列
# 3.可视化效果(样本点,回归直线)
fig = plt.figure(1, figsize=(6, 4))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.set_xlim(0, 9)
ax.set_ylim(0.3, 1.5)
ax.scatter(x_data, y_data, c='g', marker='.')
# 绘制直线
x_pos = np.linspace(1.5, 8.5, 100, dtype=np.float)
# print(x_pos) # (50, 1)
x_pra = np.zeros(shape=(x_pos.shape[0], 2), dtype=np.float)
x_pra[:, 0] = x_pos
x_pra[:, 1] = 1
# print(x_pra) # 50行 2列
# 计算直线的y坐标
y_pra = np.matmul(x_pra, w)
# print(y_pra)
# y_spa 最好做一个形状变换
ax.plot(x_pos, y_pra, color=(1, 0, 0, 1)) # color=(1, 0, 0, 1)???
fig.show(warn=False)
- 注意:要记住矩阵的计算规则
(M行, N列) * (N行, Z列) = (M行, Z列)
- 待处理:
- color=(1, 0, 0, 1) RGBA,最后一个是A(Alpha),即透明度(0-1)
6 sklearn实现
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import numpy.linalg as la
import sklearn.linear_model as lm
x_data = np.loadtxt('ex2x.dat') # 年龄
y_data = np.loadtxt('ex2y.dat') # 身高
# 训练
# 数据格式整理
# Reshape your data either using array.reshape(-1, 1) if your data has a single feature or array.reshape(1, -1) if it contains a single sample.
# 如果是一维特征,使用reshape处理单特征形状(-1, 1),如果只有一个样本,形状reshape(1,-1)
x = x_data.reshape(-1, 1) # # -1表示行数不确定
y = y_data
reg = lm.LinearRegression()
reg.fit(x, y)
p1 = reg.coef_
p2 = reg.intercept_
# print(p1, p2, sep='\n')
fig = plt.figure('机器学习sklearn可视化', figsize=(6, 4))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], label='年龄与身高')
ax.set_xlim(0, 10)
ax.set_ylim(0, 1.5)
ax.set_xlabel('年龄')
ax.set_xlabel('身高')
# 绘制训练样本
ax.scatter(x_data, y_data, color='g', marker='.', label='训练样本')
# 绘制回归直线
# 设置X坐标,直接使用后上面的x_data
x_pos = x_data
# 计算Y坐标,使用线性回归的预测值
y_pos = reg.predict(x)
# 绘制直线
ax.plot(x_pos, y_pos, color='r', label='线性回归')
ax.legend()
plt.show()
7 总结
1.通过数据可视化选择模型,选择线性模型是根据直觉和经验
2.把线性模型用数学表达式表示: =
3.可以看出已知点不完全在直线,存在误差,误差的表达:
4.误差的规律满足高斯分布(正太分布),根据高斯函数计算出误差出现的概率
5.若训练样本已知就可以计算出所有训练样本同时出现误差的概率(极大似然函数)
6.计算出w值,误差越小,直线越符合要求
7.函数实现
二、Ridge回归
1 岭回归
原理:在线性回归估计中,加上,解决线性回归出现不可逆的情况,只要
,则整个矩阵可逆
- 注:岭回归使用了单位矩阵乘以常数λ,我们观察其中的单位矩阵I,可以看到值1贯穿整个对角线,其余元素全是0.形象的,在0构成的平面上有一条1组成的“岭”,这就是岭回归中“岭”的由来
2 岭回归算法
-
,其中
- 通过代码检验效果是可以
- 通过数学的推导,来证明岭回归是可信:岭回归的数学本质
3 岭回归的代码实现
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import numpy.linalg as la
# 加载数据
data = np.loadtxt('ex0.txt')
# print(data)
x_data = data[:, 1]
y_data = data[:, 2]
x = np.zeros((x_data.shape[0], 2), dtype=np.float)
x[:, 0] = x_data
x[:, 1] = 1
# print(x)
y = y_data.reshape((y_data.shape[0], 1))
# print(y)
# 计算W(假设参数lambda)
# (𝑋𝑇𝑋+𝜆𝐼)−1𝑋𝑇𝑌
p_lambda = 0.001
s1 = np.matmul(x.T, x)
# print(x.shape) # (200, 2)
s2 = s1 + p_lambda * np.eye(x.shape[1])
# print(s2)
s3 = la.inv(s2)
s4 = np.matmul(s3, x.T)
w = np.matmul(s4, y)
# print(w)
# 预测
# 构建n个虚拟的样本,计算预测值
num = 100
x_ = np.linspace(-0.01, 1.1, num)
x_test = np.zeros((num, 2), dtype=np.float)
x_test[:, 0] = x_
x_test[:, 1] = 1
y_test = np.matmul(x_test, w)
fig = plt.figure('岭回归', figsize=(6, 4))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.scatter(x_data, y_data, s=9, c='r')
ax.plot(x_, y_test, color=(0, 0, 1, 0.2))
plt.show()

4 使用sklearn实现岭回归
import numpy as np
from sklearn.linear_model import Ridge
regression = Ridge(0.001, fit_intercept=True)
data = np.genfromtxt('ex0.txt')
# print(data.shape)
x_data = data[:, 1]
y_data = data[:, 2]
x_data = x_data.reshape(-1, 1)
y_data = y_data.reshape(-1, 1)
regression.fit(x_data, y_data)
print(regression.coef_)
print(regression.intercept_)
num = 100
x_ = np.linspace(-0.01, 1.1, num)
x_test = np.zeros((num, 2), dtype=np.float)
x_test[:, 0] = x_
x_test[:, 1] = 1
y_test = np.matmul(x_test, w)
fig = plt.figure('岭回归', figsize=(6, 4))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.scatter(x_data, y_data, s=9, c='r')
ax.plot(x_, y_test, color=(0, 0, 1, 0.5))
plt.show()
[[1.69522337]]
[3.00779172]

5 岭回归总结
- 岭回归是从最小二乘法不可逆的情况发现岭回归的数学模型
- 假设数据服从线性模型
- 线性模型存在误差
- 误差(误差的后验模型):测量误差:
满足正态分布
,系数误差也存在,而且满足正态分布
- 同样得到概率计算:概率似然函数
- 概率最大,误差最小,求最大值(推导)
- 最小值模型:损失函数
-
,一般
必须取>0得数。
三、LASSA回归
1 回归模型
1.决策模型
2.损失函数模型
3.误差模型:
分布,且
2 LASSO回归实现
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model, datasets, preprocessing
# 数据集
data = np.genfromtxt('ex0.txt')
x_data = data[:, 1]
y_data = data[:, 2]
# 数据可视化
x_data = x_data.reshape(x_data.shape[0], 1)
y_data = y_data.reshape(x_data.shape[0], 1)
alpha = 0.001
regression = linear_model.Lasso(alpha=alpha, fit_intercept=True)
regression.fit(x_data, y_data)
pre = regression.predict(x_data)
pre = pre.reshape(pre.shape[0], 1)
fig = plt.figure('数据集可视化', figsize=(6, 4))
ax = fig.add_axes([0.1,0.1,0.8,0.8], xlabel='X', ylabel='Y')
ax.scatter(x_data, y_data, color=(0, 0, 1, 1), marker='.')
ax.plot(x_data, pre, color=(1, 0, 0, 1))
plt.grid(True)
plt.show()

四、局部加权回归
1 局部加权回归来源
局部加权回归(Locally Weighted Linear Regression:LWLR)
局部加权回归是解决线性回归欠拟合问题二提出的。
解决问题的出发点是:线性回归的最终核心是使均方差函数最小(最小均方误差),局部加权是引入加权的方式,降低均方误差,使得拟合性的度量结果更好。
因为线性拟合中的均方差是无偏的,适当引入一些偏差,可以有效降低均方差。
2 局部加权模型
其中就是局部加权系数。
其中加权系数的确定是一个麻烦的事情,该系数必须确保,预测样本点离已知样本越远加权系数越小,预测样本点离已知样本越近加权系数越大。如果大家还记得正态分布(高斯分布)函数的性质,如果在0点取值1,在接近无穷远点,取值0。我们就利用正态分布这个特性,可以取,其其他位置的元素都为0,对角线上的值为:
矩阵形式是:
如果采用最下二乘法推导损失函数的最小值,可以得到最终的W计算公式:
- 怎么设计
使得
越大,
越小。 :正态分布满足这个特性。
3 局部加权回归的实现
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
# 求一个样本的局部权重预测值(下面函数按照多维模式,但只考虑1维情况)
class LWLinearRegression:
def __init__(self, sample_x, label_y, sigma=1.0):
self.X = sample_x
self.Y = label_y
self.sigma = sigma
def train_one_sample(self, data):
# data 测试样本
# 数据加权预测值
# 数据格式化
# 1. 计算局部加权矩阵
local_weight = np.zeros(
shape=(self.X.shape[0], self.X.shape[0]), dtype=np.float32)
for idx in range(local_weight.shape[0]):
# 求差
diff = data - self.X[idx, :]
# 求平方,然后除以sigma
sqrt = np.matmul(diff, diff.T) / (-2.0 * (self.sigma**2))
# 计算局部加权矩阵的对角线
local_weight[idx, idx] = np.exp(sqrt)
# 2. 计算线性回归系数矩阵
# 这里应该先做一个奇异值判定(我们暂时不去判定,等系统处理发生的异常)
W = np.matmul(
np.matmul(
np.matmul(
np.linalg.inv(
np.matmul(np.matmul(self.X.T, local_weight), self.X)),
self.X.T), local_weight), self.Y)
# 3.计算预测值
out_value = np.matmul(data, W)
return out_value
def train(self, datasets):
Y = np.zeros(shape=(datasets.shape[0], 1), dtype=np.float)
# 循环计算预测值
for idx in range(datasets.shape[0]):
Y[idx] = self.train_one_sample(datasets[idx])
return Y
# 数据初始化
data = np.loadtxt('ex0.txt')
X_DATA = data[:, 1]
Y_DATA = data[:, 2]
# 数据格式化
X = np.zeros(shape=(X_DATA.shape[0], 2), dtype=np.float) # 考虑偏置项,在测试特征加一维
Y = Y_DATA.reshape(Y_DATA.shape[0], 1)
X[:, 0] = X_DATA
X[:, 1] = 1
sigma = 0.003
lwlr = LWLinearRegression(X, Y, sigma)
# 使用训练集作为测试集
predict = lwlr.train(X)
#print(predict)
# 可视化
figure = plt.figure('数据集可视化', figsize=(6, 4))
ax = figure.add_axes([0.1, 0.1, 0.8, 0.8], xlabel='X', ylabel='Y')
ax.set_xlim(-0.2, 1.2)
ax.set_ylim(1, 5.5)
ax.scatter(X_DATA, Y_DATA, label='不知名数据集', marker='.', color=(1, 0, 0, 1))
# 排序显示
# 得到排序索引
sort_idx = X_DATA.argsort(0)
# 得到排序的结果
X_SORT = X_DATA[sort_idx]
Y_SORT = predict[sort_idx]
ax.plot(X_SORT, Y_SORT, label='线性拟合', color='b', linewidth=3)
ax.legend()
plt.show()

网友评论