线性回归学习及实现

线性回归学习及实现

线性回归的原理

用一条直线来拟合数据样本,求得该直线的回归系数,这个过程就叫做回归,然后将回归系数带入直线回归方程,最后将待预测数据带入回归方程得到预测结果。

线性回归的优缺点

优点:结果易于理解,计算上不复杂。

缺点:对非线性的数据拟合不好。

适用数据类型:数值型和标称型数据。

线性回归算法分析

1.假设样本数据拟合一条直线
2.验证回归预测结果的准确度,需要用实际值(y)减去预测值( y ^ )的和求最小化
3.为便于求解最小值,演化成求 i = 1 m ( y i y ¯ i ) 2 的最小值
4.获得最小值对应的回归系数

简单线性回归-最小二乘法

假设我们找到了最佳拟合直线方程: y ^ = a x + b 根据每一个样本点 x i ,都对应有一个预测结果 y ^ i = a x i + b ,真实值为 y i 目标找到a和b使得: i = 1 m ( y i y ¯ i ) 2 ,即 i = 1 m ( y i a x i b ) 2 尽可能的小。

目标函数(损失函数)为:

J ( a , b ) = i = 1 m ( y i a x i b ) 2

要使得 J ( a , b ) 最小,转化为求极值。其中未知参数a和b,那么分别对a和b求导。

J ( a , b ) a = 0
J ( a , b ) b = 0

对b求导

J ( a , b ) a = i = 1 m 2 ( y i a x i b ) ( 1 ) = 0

进一步推导得(两边除以2):

i = 1 m ( y i a x i b ) ( 1 ) = i = 1 m y i a i = 1 n x i m b = 0

进一步推导,两边同时除以m:

i = 1 m y i a i = 1 n x i m b = 0 i = 1 m y i a i = 1 n x i = m b b = y ¯ a x ¯

对a求导

J ( a , b ) a = i = 1 m 2 ( y i a x i b ) ( x i ) = 0 i = 1 m ( y i a x i b ) x i = 0

b = y ¯ a x ¯ 带入:

i = 1 m ( y i a x i y ¯ + a x ¯ ) x i = 0 i = 1 m ( y i x i a ( x i ) 2 y ¯ x i + a x ¯ x i ) = 0 i = 1 m ( y i x i y ¯ x i ) i = 1 m ( a ( x i ) 2 a x ¯ x i ) = 0 i = 1 m ( y i x i y ¯ x i ) = a i = 1 m ( ( x i ) 2 x ¯ x i )

最后获得a的表达式:

a = i = 1 m ( y i x i y ¯ x i ) i = 1 m ( ( x i ) 2 x ¯ x i ) i = 1 m ( y i x i y ¯ x i x ¯ y i + x ¯ y ¯ ) i = 1 m ( ( x i ) 2 x ¯ x i x ¯ x i + x ¯ 2 ) i = 1 m ( x i x ¯ ) ( y i y ¯ ) i = 1 m ( x i x ¯ ) 2

将获得的a向量化处理(向量的点乘计算):

i = 1 m W i V i W V W = ( w 1 , w 2 , . . w m ) , V = ( v 1 , v 2 . . . v m )

a = i = 1 m ( x i x ¯ ) ( y i y ¯ ) i = 1 m ( x i x ¯ ) 2 ( x i x ¯ ) ( y i y ¯ ) ( x i x ¯ ) ( x i x ¯ )

简单线性回归代码实现

class LinearRegression():

    def __init__(self):
        '''初始化LinearRegression分类器'''
        self.ceof_ = None
        self.interp_ = None

    def fit(self,x_train,y_train):
        '''训练分类器,获取对应的回归系数和截距'''
        # 求X和y的均值
        x_mean = np.mean(x_train)
        y_mean = np.mean(y_train)

        # 分子num
        num = (x_train-x_mean).dot(y_train-y_mean)
        # 分母d
        d = (x_train-x_mean).dot(x_train-x_mean)
        self.ceof_ = num /d
        self.interp_ = y_mean - self.ceof_*x_mean

        return self

    def predict(self,x_test):

        y_predict = [self.ceof_ * x + self.interp_ for x in x_test]

        return y_predict

    def __repr__(self):
        return 'LinearRegression(vector)'

多元线性回归分析及代码实现

多元线性回归分析

假设我们的数据拟合直线y:

y = θ 0 + θ 1 x 1 + θ 2 X 2 . . . + θ n x n

注释: y ^ = θ 0 + θ 1 x 1 i + θ 2 X 2 i + θ n x n i x i = ( x 1 i , x 2 i , x 3 i , x n i ) , i i , n x i n θ = ( θ 0 , θ 1 , θ 2 , . . , θ n )

那么只要得到一组 θ 值,既可以求得对应的新样本的预测值 y ^

y ^ 推到成 y ^ = θ 0 x 0 i + θ 1 x 1 i + θ 2 X 2 i . . . + θ n x n i , x 0 i = 1

那么第i个样本 x i 可以表示为 :

x i = ( x 0 i , x 1 i , x 2 i , . . . , x n i ) = ( 1 , x 1 i , x 2 i , . . . , x n i )

其中 θ 为一个列向量:

θ = ( θ 0 , θ 1 , θ 2 , . . . . . , θ n ) T

最后每一个样本的预测值 y ^ i :

y ^ i = x i θ

样本集合set可以表示为:

X b = ( 1 x 1 1 x 2 1 x n 1 1 x 1 2 x 2 2 x n 2 1 x 1 m x 2 m x n m )

那么 y ^ 可以写成矩阵运算

y ^ = X b θ

目标函数(损失函数)尽可能的小:

J ( θ ) = i = 1 m ( y i y ^ i ) 2 ( y X b θ ) T ( y X b θ )

J ( θ ) θ 0 θ

θ = ( X b T X b ) 1 X b T y

问题:时间复杂度高 O ( n 3 )
注:-1 表示矩阵的逆, θ 是矩阵

多元线性回归(正规方程解)实现封装

import numpy as np
from sklearn.metrics import r2_score
class LinearRegression2():
    def __init__(self):
        '''初始化分类器'''
        self.coef_ = None
        self.interp_ = None
        self.theta_ = None

    def fit(self, X_train, y_train):
        '''训练分类器'''
        assert X_train.shape[0] == y_train.shape[0],'The size of X_train must be equal to y_train`s'

        X_b = np.hstack( [np.ones((len(X_train),1)), X_train] )

        self.theta_ = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)
        self.coef_ = self.theta_[1:]
        self.interp_ = self.theta_[0]
        return self

    def predict(self,X_test):
        assert self.interp_ is not None and self.coef_ is not None, 'Must be fit before predict!'
        assert X_test.shape[1] == len(self.coef_), 'The feather`s number of X_test must be equal to the length of self.coef_'

        X_b =  np.hstack( [np.ones((len(X_test),1)), X_test] )
        y_predict = X_b.dot(self.theta_)

        return y_predict

    def score(self, X_test, y_test):
        y_predict = self.predict(X_test)
        return r2_score(y_test, y_predict)

    def __repr__(self):
        return 'LinearRegression(mat)'

多元线性回归(梯度下降法)实现封装

注意:使用梯度下降法求解极值,需要对数据特征进行归一化处理。

import numpy as np
from sklearn.metrics import r2_score

class LinearRegression:

    def __init__(self):
        """初始化Linear Regression模型"""
        self.coef_ = None
        self.intercept_ = None
        self._theta = None

    def fit_normal(self, X_train, y_train):
        """训练Linear Regression模型"""
        assert X_train.shape[0] == y_train.shape[0], \
            "the size of X_train must be equal to the size of y_train"

        X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
        self._theta = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y_train)

        self.intercept_ = self._theta[0]
        self.coef_ = self._theta[1:]

        return self

    def fit_gd(self, X_train, y_train, eta=0.01, n_iters=1e4):
        """使用梯度下降法训练Linear Regression模型"""
        assert X_train.shape[0] == y_train.shape[0], \
            "the size of X_train must be equal to the size of y_train"

        def J(theta, X_b, y):
            try:
                return np.sum((y - X_b.dot(theta)) ** 2) / len(y)
            except:
                return float('inf')

        def dJ(theta, X_b, y):
            return X_b.T.dot(X_b.dot(theta) - y) * 2. / len(X_b)

        def gradient_descent(X_b, y, initial_theta, eta, n_iters=1e4, epsilon=1e-8):

            theta = initial_theta
            cur_iter = 0

            while cur_iter < n_iters:
                gradient = dJ(theta, X_b, y)
                last_theta = theta
                theta = theta - eta * gradient
                if (abs(J(theta, X_b, y) - J(last_theta, X_b, y)) < epsilon):
                    break

                cur_iter += 1

            return theta

        X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
        initial_theta = np.zeros(X_b.shape[1])
        self._theta = gradient_descent(X_b, y_train, initial_theta, eta, n_iters)

        self.intercept_ = self._theta[0]
        self.coef_ = self._theta[1:]

        return self

    def fit_sgd(self, X_train, y_train, n_iters=5, t0=5, t1=50):
        """使用随机梯度下降法训练Linear Regression模型"""
        assert X_train.shape[0] == y_train.shape[0], \
            "the size of X_train must be equal to the size of y_train"
        assert n_iters >= 1

        def dJ_sgd(theta, X_b_i, y_i):
            return X_b_i * (X_b_i.dot(theta) - y_i) * 2.

        def sgd(X_b, y, initial_theta, n_iters, t0=5, t1=50):

            def learning_rate(t):
                return t0 / (t + t1)

            theta = initial_theta
            m = len(X_b)

            for cur_iter in range(n_iters):
                indexes = np.random.permutation(m)
                X_b_new = X_b[indexes]
                y_new = y[indexes]
                for i in range(m):
                    gradient = dJ_sgd(theta, X_b_new[i], y_new[i])
                    theta = theta - learning_rate(cur_iter * m + i) * gradient

            return theta

        X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
        initial_theta = np.random.randn(X_b.shape[1])
        self._theta = sgd(X_b, y_train, initial_theta, n_iters, t0, t1)

        self.intercept_ = self._theta[0]
        self.coef_ = self._theta[1:]

        return self

    def predict(self, X_predict):
        """给定待预测数据集X_predict,返回表示X_predict的结果向量"""
        assert self.intercept_ is not None and self.coef_ is not None, \
            "must fit before predict!"
        assert X_predict.shape[1] == len(self.coef_), \
            "the feature number of X_predict must be equal to X_train"

        X_b = np.hstack([np.ones((len(X_predict), 1)), X_predict])
        return X_b.dot(self._theta)

    def score(self, X_test, y_test):
        """根据测试数据集 X_test 和 y_test 确定当前模型的准确度"""

        y_predict = self.predict(X_test)
        return r2_score(y_test, y_predict)

    def __repr__(self):
        return "LinearRegression()"

本学习笔记参考:
《机器学习实战》和《Python3入门机器学习 经典算法与应用》

猜你喜欢

转载自blog.csdn.net/paopaohll/article/details/81676127