美文网首页
learnfromzero_0

learnfromzero_0

作者: 无天_1cae | 来源:发表于2019-04-29 20:10 被阅读0次

一、线性回归

1 流程

  • 线性回归:
    • 1 通过可视化寻找模型->
    • 2 表示和推导模型->
      • 表示方式使用矩阵,向量内积、点积 y_i = Wx_i
    • 3 模型存在误差->
    • 4 计算出现误差的概率->
      • 误差表达式 y = Wx+\epsilon,误差满足高斯分布(正太分布),根据高斯概率密度函数,已知误差就可以计算出现误差的概率;若训练样本已知可以计算出现误差的概率(最大似然函数)
    • 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
  • reshape ---> 转换形状 url同matmul
    • np.reshape(x, (a, b)) x:原矩阵,(a, b):要转变的形状
      • 如果reshape的第一个参数是None或者-1,表明行数是不确定的
  • 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维的元素后,进行乘法运算。
  • 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()
1.png
(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)

2.png
  • 下面测试和验证细节、矩阵计算
##########################################################
%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.把线性模型用数学表达式表示:y = Wx = w_1x_1 + w2x_2 + \dots +w_nx_n + b
3.可以看出已知点不完全在直线,存在误差,误差的表达:y = W x + \epsilon
4.误差的规律满足高斯分布(正太分布),根据高斯函数计算出误差出现的概率
5.若训练样本已知就可以计算出所有训练样本同时出现误差的概率(极大似然函数)
6.计算出w值,误差越小,直线越符合要求
7.函数实现

二、Ridge回归

1 岭回归

原理:在线性回归估计中,加上\lambda I,解决线性回归出现不可逆的情况,只要\lambda > 0,则整个矩阵可逆

  • 注:岭回归使用了单位矩阵乘以常数λ,我们观察其中的单位矩阵I,可以看到值1贯穿整个对角线,其余元素全是0.形象的,在0构成的平面上有一条1组成的“岭”,这就是岭回归中“岭”的由来

2 岭回归算法

  • W=(X^TX + \lambda I)^{-1}X^TY ,其中\lambda > 0
    • 通过代码检验效果是可以
    • 通过数学的推导,来证明岭回归是可信:岭回归的数学本质

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()
3.png

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]
4.png

5 岭回归总结

  1. 岭回归是从最小二乘法不可逆的情况发现岭回归的数学模型
  2. 假设数据服从线性模型Y=XW
  3. 线性模型存在误差
  4. 误差(误差的后验模型):测量误差:\epsilon满足正态分布N(0, \sigma),系数误差也存在,而且满足正态分布N(0, \tau)
  5. 同样得到概率计算:概率似然函数L(W)
  6. 概率最大,误差最小,求最大值(推导)
  7. 最小值模型:损失函数 \dfrac{1}{2} \sum \limits _{i=1}^n (y_i-x_iW)^2+ \lambda \sum \limits _{i=1}^n {w_i}^2
  8. \lambda= \dfrac{1}{\tau ^2},一般\lambda必须取>0得数。

三、LASSA回归

1 回归模型

1.决策模型

y=xW

2.损失函数模型

J(W)=\dfrac{1}{2}( \sum \limits _{i=1}^{n} (y_i - x_iW)^2 + \lambda \sum \limits _{i=1}^{k} {|w_i|} )

3.误差模型:
y=xW + \epsilon
\epsilon \sim N(0, \sigma ^ 2)分布,且w_i \sim Laplace(0,b)
f(x)=\dfrac{1}{2 b} exp{ (- \dfrac{|x-\mu|}{ b } )}

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()

5.png

四、局部加权回归

1 局部加权回归来源

  局部加权回归(Locally Weighted Linear Regression:LWLR)
  局部加权回归是解决线性回归欠拟合问题二提出的。
  解决问题的出发点是:线性回归的最终核心是使均方差函数最小(最小均方误差),局部加权是引入加权的方式,降低均方误差,使得拟合性的度量结果更好。
  因为线性拟合中的均方差是无偏的,适当引入一些偏差,可以有效降低均方差。

2 局部加权模型

  W=(X^T\bar{W}X)^{-1}X^T\bar{W}y
  其中\bar{W}就是局部加权系数。
  
  其中加权系数的确定是一个麻烦的事情,该系数必须确保,预测样本点离已知样本越远加权系数越小,预测样本点离已知样本越近加权系数越大。如果大家还记得正态分布(高斯分布)函数的性质,如果在0点取值1,在接近无穷远点,取值0。我们就利用正态分布这个特性,可以取\bar{W},其其他位置的元素都为0,对角线上的值为:
  \bar{W}(i,i)=exp(\dfrac{(x^{(i)}-x)^2}{-2{\sigma}^2})
  矩阵形式是:
  \bar{W}(i,i)=exp(\dfrac{(x^{(i)}-x)(x^{(i)}-x)^T}{-2{\sigma}^2})
  如果采用最下二乘法推导损失函数的最小值,可以得到最终的W计算公式:
W=(X^T\bar{W}X)^{-1}X^T\bar{W}y

  • 怎么设计p_i使得(xW-y)越大,p_i越小。 :正态分布满足这个特性。

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()
6.png

相关文章

  • learnfromzero_0

    一、线性回归 1 流程 线性回归:1 通过可视化寻找模型->2 表示和推导模型->表示方式使用矩阵,向量内积、点积...

网友评论

      本文标题:learnfromzero_0

      本文链接:https://www.haomeiwen.com/subject/vglxjqtx.html