线性回归,最小二乘,局部加权,岭回归,huberloss

这是一次统计学的作业

线性模型

今天我们所知道的回归是由达尔文(Charles Darwin)的表兄弟Francis Galton发明的。Galton
于1877年完成了第一次回归预测,目的是根据上一代豌豆种子(双亲)的尺寸来预测下一代豌
豆种子(孩子)的尺寸。Galton在大量对象上应用了回归分析,甚至包括人的身高。他注意到,
如果双亲的高度比平均高度高,他们的子女也倾向于比平均高度高,但尚不及双亲。孩子的高
度向着平均高度回退(回归)。Galton在多项研究上都注意到这个现象,所以尽管这个英文单
词跟数值预测没有任何关系,但这种研究方法仍被称作回归.

第一步:准备数据

建立一个函数名字,叫load_data,目的为打开一个TAB键分隔的文本文件,返回值数据与类标。

注意:目标数据集ex0有两三列,第一二列为数据,三列为标签

import numpy as np
#load data from file导入txt数据
def load_data(filename):
    dataset = []
    label = []
    file = open(filename)
    for line in file.readlines():
        lineArr = line.strip().split('\t')
        dataset.append(lineArr[0:2])
        label.append(lineArr[-1])    
    return np.array(dataset,dtype=np.float64),\
           np.array(label,dtype=np.float64).reshape(-1,1)

第二步 可视化画图

import matplotlib.pyplot as plt
#导入数据并且可视化一下
x,y = load_data("C:/Users/Nicht_sehen/Desktop/ex0.txt")
print(x.shape,y.shape)
print(x[0],y[0])


plt.scatter(x[:,1],y[:,0],marker='x',color = 'r')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
(200, 2) (200, 1)
[1.       0.067732] [3.176512]

在这里插入图片描述

第三步 带入正规方程求解,画画图看拟合效果

#简单的线性回归,使用求导公式就可以求得w的最优值

def normalEquation(X_train,y_train):
    w = np.zeros((X_train.shape[0],1))
    #这里用的伪逆,所以不用判断矩阵的逆存不存在
    w = ((np.linalg.pinv(X_train.T.dot(X_train))).dot(X_train.T)).dot(y_train)
    return w
w = normalEquation(x,y)
print(w)


[[3.00774323]
 [1.69532267]]
#现在可视化一下求得w的效果
plt.scatter(x[:,1],y[:,0],marker='.',color = 'r')
plt.plot(x[:,1],x.dot(w),color = "blue",linestyle = "-")
plt.xlabel('x')
plt.ylabel('y')
plt.show()

在这里插入图片描述

第四步 试试加权最小乘回归

随机生成权重,练习加权最小二乘回归

def gaussi_w(x,y,k=0.1):
    m =np.shape(x)[0]
    w = np.mat(np.eye(m))
    p=np.zeros(m)
    x =np.mat(x)
    for i in range(m):
            for j in range(m):
                s = x[i,]-x[j,]
                w[j,j]=np.exp(s@s.T/(-2.0*k**2))
            xTx = x.T@(w@x)
            xTy = x.T@(w@y)
            wb = np.linalg.pinv(xTx)@xTy
            p[i] = x[i]*wb
    return p


p = gaussi_w(x,y,0.01)
Index = argsort(x[:,1],0)
xsort = x[Index][:]

print(p.shape)
plt.scatter(x[:,1],y[:,0],marker='.',color = 'r')
plt.plot(xsort[:,1],p[Index],color = "blue",linestyle = "-")
plt.xlabel('x')
plt.ylabel('y')
plt.show()

(200,)

在这里插入图片描述

五 岭回归

#当数据的特征非常的多,n>m时,则输入数据X不是满秩矩阵,非满秩矩阵求逆会有问题
#岭回归 == 加入了正则化,缩减权重系数,也就是减少特征值数量

#岭回归公式求解
def ridgeRegress(x,y,lammda = 0.2):
    m,n = x.shape
    I = np.eye((n))
    temp = x.T.dot(x) + lammda * I
    w = np.linalg.pinv(temp).dot(x.T).dot(y)    
    return w
w = ridgeRegress(x,y)
print(w)

#现在可视化一下求得w的效果
plt.scatter(x[:,1],y[:,0],marker='.',color = 'r')
plt.plot(x[:,1],x.dot(w),color = "blue",linestyle = "-")
plt.xlabel('x')
plt.ylabel('y')
plt.show()
[[3.00602277]
 [1.69269003]]

在这里插入图片描述

再试一种Huber损失、或者Tukey损失函数最小二乘回归

from sklearn.linear_model import HuberRegressor

huber = HuberRegressor().fit(x, y)
p = huber.predict(x)

plt.scatter(x[:,1],y[:,0],marker='.',color = 'r')
plt.plot(x[:,1],p,color = "blue",linestyle = "-")
plt.xlabel('x')
plt.ylabel('y')
plt.show()

在这里插入图片描述

六 万能算法ADMM求解Lasso

初学者写时不建议用类

import numpy as np
import matplotlib.pyplot as plt
from math import sqrt, log
## 这个是l1范数截断算子
def Sthresh(x, gamma):
    return np.sign(x)*np.maximum(0, np.absolute(x)-gamma)

def ADMM(A, y):

    m, n = A.shape
    w, v = np.linalg.eig(A.T.dot(A))
    MAX_ITER = 10000
    rho=0.01

    # 求解问题 min 1/2(y - Ax) + l||x||"
    # 初始化
    xhat = np.zeros([n, 1])
    zhat = np.zeros([n, 1])
    u = np.zeros([n, 1])

    # 初始化步长
    l = sqrt(2*log(n, 10))
    AtA = A.T.dot(A)
    Aty = A.T.dot(y)
    # 为了可逆
    Q = AtA + 0.01*np.identity(n)
    Q = np.linalg.inv(Q)

    i = 0

    while(i < MAX_ITER):
        # x 更新
        xhat = Q.dot(Aty + rho*(zhat - u))

        # z 更新 0.1 为可调参数
        zhat = Sthresh(xhat + u, 0.1)

        # 对偶变量更新
        u = u + xhat - zhat

        i = i+1
    return xhat,  l

合成数据试一试

A = np.random.randn(50, 200)

num_non_zeros = 10
positions = np.random.randint(0, 200, num_non_zeros)
amplitudes = 100*np.random.randn(num_non_zeros, 1)
x = np.zeros((200, 1))
x[positions] = amplitudes

y = A.dot(x) + np.random.randn(50, 1)

xhat,  l = ADMM(A, y)

plt.plot(x, label='合成值')
plt.plot(xhat, label = '估计值')

plt.legend(loc = 'upper right')

plt.show()
发布了125 篇原创文章 · 获赞 56 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/Nicht_sehen/article/details/100728912