机器学习 Python 线性回归简单代码实现

时间:2020-9-13 作者:admin

线性回归模型

概述

​ 机器学习整体大致可以分为两大类,分别就是回归与分类。线性回归和逻辑回归是两种最基本的模型,其它模型也大致是从这两类中演变来的,所以这两个模型算是机器学习的入门模型,虽然sklearn库中都有直接的代码可以调用,但是理解其原理,并自己手动实现还是很有必要的。

模型概述

​ 所谓线性回归就是用一条直线去拟合数据,回归两字来自于遗传学,意思是回到平均水平。其简单形式为y = wx + b,我们要做的就是寻找到最合适的w和b,让预测准与真实值之间的误差最小,要想找到最合适的w和b,有两种方法,一种就是最小二乘法,一种就是梯度下降法。

​ 有一说一,公式太难打了,主要公式如下面图片所示:
机器学习 Python 线性回归简单代码实现

python代码实现

class Linear_Regression:
    """
    实现简单线性回归
    """
    def __init__(self):
        pass
    
    def train_gradient_descent(self, X, y, learning_rate=0.01,iters=100):
        """
        用梯度下降法求参数
        ----------
        X : 自变量数据,形状为(m,n),m:数据的个数,n:自变量(或者特征)的个数
        y : 因变量数据,形状为(m,1)
        learning_rate : 学习速率,默认为0.01
        iters : 迭代次数,默认为100
        ----------
        """
        n_samples = X.shape[0]
        n_features = X.shape[1]
        #初始化参数
        self.w = np.zeros(shape=(n_features,1))
        self.b = 0
        
        costs = []
        for i in range(iters):
            # 计算预测值
            y_predict = np.dot(X, self.w) + self.b
           
            # 计算损失函数
            cost = np.sum((y_predict - y)**2) / (2*n_samples)
            costs.append(cost)
           
            if i % 100 == 0:
                print(f"Cost at iteration {i}: {cost}")
            
            # 计算梯度
            dw = (1 / n_samples) * np.dot(X.T, (y_predict - y))
            db = (1 / n_samples) * np.sum((y_predict - y)) 
            
            # 更新梯度
            self.w = self.w - learning_rate * dw
            self.b = self.b - learning_rate * db
        
        return self.w, self.b, costs
   
    def train_normal_equation(self, X, y):
        """
        最小二乘法,方程式法计算
        """
        X = np.column_stack((np.ones(X.shape[0]),X))
        X = np.matrix(X)
        y = np.matrix(y)
        
        coef = (X.T*X).I*X.T*y
        self.w = coef[0]
        self.b= coef[1:]
        return self.w, self.b
        
    def predict(self, X):
        return np.dot(X, self.w) + self.b

简单实例验证

生成数据

生成数据代码如下:

X = np.random.rand(500,3) #生成形状为(500,3)的数据
coef = np.array([2,0.2,1.5]) #生成斜率项
y = 5 + np.dot(X,coef) #计算因变量值,形状为(500,)
y = y[:,np.newaxis] #改变y值形状为(500,1)

梯度下降法计算

运行如下代码:

linear_regression = Linear_Regression()
grd = linear_regression.train_gradient_descent(X,y,learning_rate=0.1,iters=1000)
print("-"*50)
print(f"斜率项为:\n{grd[0]}")
print(f"截距项为:\n{grd[1]}")
print("-"*50)

代码运行结果如下:

Cost at iteration 0: 23.908020401267393
Cost at iteration 100: 0.042615847946421086
Cost at iteration 200: 0.014364230409000197
Cost at iteration 300: 0.005176592296081314
Cost at iteration 400: 0.0019494499429811344
Cost at iteration 500: 0.0007538294158717608
Cost at iteration 600: 0.00029592278743143565
Cost at iteration 700: 0.00011713723139089097
Cost at iteration 800: 4.657686237953135e-05
Cost at iteration 900: 1.856514407834283e-05
--------------------------------------------------
斜率项为:
[[2.00696415]
 [0.20748925]
 [1.50849497]]
截距项为:
4.987877313714786
--------------------------------------------------

最小二乘法计算

运行如下代码:

ols = Linear_Regression().train_normal_equation(X,y)
print('-'*50)
print(f"斜率项为:\n{ols[1]}")
print(f"截距项为:\n{ols[0]}")
print('-'*50)

代码运行结果如下:

--------------------------------------------------
斜率项为:
[[2. ]
 [0.2]
 [1.5]]
截距项为:
[[5.]]
--------------------------------------------------

结语

​ 基于最小二乘法改进的模型还有很多,如岭回归、Lasso回归、elasticnet回归等,其中岭回归用的是L2正则化,Lasso回归用的是L1正则化,elasticnet回归是两者结合。

​ 希望本文对大家有所帮助,有空再写一下逻辑回归的内容,谢谢大家。

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。