沽泡机器学习入门到精通(唐宇迪)

视频链接

课程简介

线性回归

线性回归问题概述

机器学习中分为两种问题: 1.回归问题;2.分类问题

  1. 分类: 比如去银行贷款,银行贷或不贷是一个分类问题(有明确类别)
  2. 回归: 去银行贷款,贷多少(有一个区间,要找出大概是哪个区间,哪个值)

至少需要x特征(数据)和y标签

x1和x2的影响不同,所以分别假设参数θ1和θ2

但是我们假设的线性方程无法覆盖所有的点(已知数据)

误差项定义

θ1 和 θ2 是权重项,θ0 是偏置项;θ1 和 θ2 改变,线的角度改变,θ0 改变,整个线的高度改变

所有数据的操作,都是对矩阵进行一系列变换

为了将 y = θ1x + θ2x + θ0 转为矩阵运算,我们添加一个 x0,改为 y = θ1x + θ2x + θ0*x0

x0的值是1,因为1*1是1(自身乘积为自身)

有时候看到别人的数据添加了一列全是 1 的,其实是为了把数据转为矩阵,方便计算


给机器数据和目标函数,让机器去学习,找出什么参数最符合该目标函数

独立同分布项的意义

似然函数的作用

独立同分布的情况下,联合概率密度 = 边缘概率密度的乘积


累乘

我们不是想求 L(θ)或 ㏒(L(θ)),这里 θ 是一组向量,我们要求其中的极值点对应的 θ。

参数求解




总体越大越好,A部分不变,B部分恒正,A-B,B(提取出下面这个式子进行最小二乘)越小越好

Xθ 是矩阵,现在要求 θ 为何时,目标函数值最小

矩阵.T * 矩阵 => 对称矩阵

为了求解最小值,则要求 J(θ)对 θ 求偏导的极值点 (&J(θ)/&(θ) = 0)


对称矩阵 A 乘 θ 和 θ 转置然后对 θ 求偏导 => &(θ^T * A * θ)/ &(θ) = 2 * A * θ

> 0 = x^T * x * θ - x^T * y
> x^T * x * θ = x^T * y
两边乘(x^T * x)^-1,即乘(x^T * x)的逆矩阵,得1
> 1 * θ = (x^T * x)^-1 * x^T * y

得出这个结果,可以根据已知量求未知量 θ

这个式子有些问题:1.没有体现机器学习的学习的过程(渐进地改变某些值);2.不是所有矩阵的逆都能成立

梯度下降

将线性回归公式当作特例(明确地可以求解),因为一般机器学习问题无法求出这种明确的解


当值梯度下降到最低点附近的小范围波动时,处于饱和状态,loss 不会再大幅度改变,梯度下降基本完成

参数更新方法

梯度下降对不同样本参数分别进行求解(偏导),然后共同决定下降的点位。θ0 对应 x0,θ1 对应 x1,x 之间没有关联,则 θ 之间也是。

因为梯度下降是往反方向(导数的负值),所以加上负号变成正的式子(θj + xxx)

优化参数设置

小批量梯度下降法的 α 参数表示学习率

线性回归实现

线性回归整体模块概述

首先准备数据 data,然后进行预处理(归一化、标准化,让维度、数据范围小一些),然后将每个特征 x 对应的 0 求出来


初始化步骤

import numpy as np
# . -> ./
from ..utils.features import prepare_for_training


class LinearRegression:
    def __init__(self, data, labels, polynomial_degree=0, sinusoid_degree=0, normalize_data=True):
        """
        初始化
        1. 数据预处理
        2. 得到所有特征个数
        3. 初始化参数矩阵
        :param data: 数据
        :param labels: 标签
        :param polynomial_degree:
        :param sinusoid_degree:
        """

        # 预处理
        (data_processed, features_mean, features_deviation) = prepare_for_training(data,
                                                                                   polynomial_degree,
                                                                                   sinusoid_degree,
                                                                                   normalize_data),
        # 预处理完的data
        self.data = data_processed
        self.labels = labels
        # mean
        self.features_mean = features_mean
        # std
        self.features_deviation = features_deviation
        self.polynomial_degree = polynomial_degree
        self.sinusoid_degree = sinusoid_degree
        self.normalize_data = normalize_data

        # 算需要求多少个θ
        num_features = self.data.shape[1]  # 列数
        self.theta = np.zeros((num_features, 1))

实现梯度下降优化模块

θ 和 x 的矩阵,θ 转置后,可以实现 θi 和 Xi 对应相乘


class LinearRegression:
    def __init__(self, data, labels, polynomial_degree=0, sinusoid_degree=0, normalize_data=True):
        """
        初始化
        1. 数据预处理
        2. 得到所有特征个数
        3. 初始化参数矩阵
        :param data: 数据
        :param labels: 标签
        :param polynomial_degree:
        :param sinusoid_degree:
        """

        # 预处理
        (data_processed, features_mean, features_deviation) = prepare_for_training(data,
                                                                                   polynomial_degree,
                                                                                   sinusoid_degree,
                                                                                   normalize_data),
        # 预处理完的data
        self.data = data_processed
        self.labels = labels
        # mean
        self.features_mean = features_mean
        # std
        self.features_deviation = features_deviation
        self.polynomial_degree = polynomial_degree
        self.sinusoid_degree = sinusoid_degree
        self.normalize_data = normalize_data

        # 算需要求多少个θ
        num_features = self.data.shape[1]  # 列数
        self.theta = np.zeros((num_features, 1))

    # alpha: 学习率,num_iterations: 迭代次数
    def train(self, alpha, num_iterations=500):

    # 梯度下降优化步骤
    def gradient_step(self, alpha):
        # 有多少个数据
        num_examples = self.data.shape[0]
        # 预测值
        prediction = LinearRegression.hypothesis(self.data, self.theta)
        # 预测值 - 真实值
        delta = prediction - self.labels
        # 更新参数
        theta = self.theta
        # 不用for循环,而是使用矩阵来实现相乘
        theta = theta - alpha * (1 / num_examples) * (np.dot(delta.T, self.data)).T

    # 预测
    @staticmethod  # 静态方法
    def hypothesis(data, theta):
        # θ * x
        predictions = np.dot(data, theta)
        return predictions

损失与预测模块

import numpy as np
# . -> ./
from ..utils.features import prepare_for_training


class LinearRegression:
    def __init__(self, data, labels, polynomial_degree=0, sinusoid_degree=0, normalize_data=True):
        """
        初始化
        1. 数据预处理
        2. 得到所有特征个数
        3. 初始化参数矩阵
        :param data: 数据
        :param labels: 标签
        :param polynomial_degree:
        :param sinusoid_degree:
        """

        # 预处理
        (data_processed, features_mean, features_deviation) = prepare_for_training(data,
                                                                                   polynomial_degree,
                                                                                   sinusoid_degree,
                                                                                   normalize_data)
        # 预处理完的data
        self.data = data_processed
        self.labels = labels
        # mean
        self.features_mean = features_mean
        # std
        self.features_deviation = features_deviation
        self.polynomial_degree = polynomial_degree
        self.sinusoid_degree = sinusoid_degree
        self.normalize_data = normalize_data

        # 算需要求多少个θ
        num_features = self.data.shape[1]  # 列数
        self.theta = np.zeros((num_features, 1))

    def train(self, alpha, num_iterations=500):
        '''
        训练,执行梯度下降
        :param alpha:
        :param num_iterations:
        :return:
        '''
        # alpha: 学习率,num_iterations: 迭代次数
        cost_history = self.gradient_descent(alpha, num_iterations)
        return self.theta, cost_history

    def gradient_descent(self, alpha, num_iterations):
        '''
        迭代模块,计算误差,更新参数
        :param alpha: 学习率
        :param num_iterations: 样本数
        :return: 历史误差
        '''
        cost_history = []
        for i in range(num_iterations):
            # 更新参数
            self.gradient_step(alpha)
            # 记录损失
            cost_history.append(self.cost_function(self.data, self.labels))
        return cost_history

    # 梯度下降优化步骤
    def gradient_step(self, alpha):
        '''
        梯度下降参数更新计算方法
        :param alpha: 学习率
        :return:
        '''
        # 有多少个数据
        num_examples = self.data.shape[0]
        # 预测值
        prediction = LinearRegression.hypothesis(self.data, self.theta)
        # 预测值 - 真实值
        delta = prediction - self.labels
        # 更新参数
        theta = self.theta
        # 不用for循环,而是使用矩阵来实现相乘
        theta = theta - alpha * (1 / num_examples) * (np.dot(delta.T, self.data)).T

    # 计算损失
    def cost_function(self, data, labels):
        '''
        损失计算方法
        :param data:
        :param labels: 真实值
        :return:
        '''
        # 样本个数
        num_example = data.shape[0]
        # 预测值 - 真实值
        loss = LinearRegression.hypothesis(self.data, self.theta) - labels
        # 使用误差算法 -> 可以自己实现其他误差算法
        # 矩阵平方 r*r.T
        cost = (1 / 2) * np.dot(loss.T, loss)
        return cost[0][0]

    @staticmethod  # 静态方法
    def hypothesis(data, theta):
        # θ * x
        predictions = np.dot(data, theta)
        return predictions

    def get_cost(self, data, labels):
        # 预处理
        data_processed = prepare_for_training(data,
                                              self.polynomial_degree,
                                              self.sinusoid_degree,
                                              self.normalize_data)[0]
        # 得到当前损失
        return self.cost_function(data_processed, labels)

    def predict(self, data):
        '''
        用训练的参数模型,预测得到回归值结果
        :param data:
        :return:
        '''
        # 预处理
        data_processed = prepare_for_training(data,
                                              self.polynomial_degree,
                                              self.sinusoid_degree,
                                              self.normalize_data)[0]
        predictions = LinearRegression.hypothesis(data_processed, self.theta)
        return predictions


  目录