机器学习项目 - 线性回归 - 基础知识

# 任意选一个你喜欢的整数,这能帮你得到稳定的结果
seed = 8

1 矩阵运算

1.1 创建一个 4*4 的单位矩阵

# 这个项目设计来帮你熟悉 python list 和线性代数
# 你不能调用任何NumPy以及相关的科学计算库来完成作业


# 本项目要求矩阵统一使用二维列表表示,如下:
A = [[1,2,3], 
     [2,3,3], 
     [1,2,5]]

B = [[1,2,3,5], 
     [2,3,3,5], 
     [1,2,5,1]]

# 向量也用二维列表表示
C = [[1],
     [2],
     [3]]

#TODO 创建一个 4*4 单位矩阵
I = [[1,0,0,0],
     [0,1,0,0],
     [0,0,1,0],
     [0,0,0,1]]

1.2 返回矩阵的行数和列数

# TODO 返回矩阵的行数和列数
def shape(M):
    return len(M),len(M[0])
# 运行以下代码测试你的 shape 函数
%run -i -e test.py LinearRegressionTestCase.test_shape

1.3 每个元素四舍五入到特定小数数位

# TODO 每个元素四舍五入到特定小数数位
# 直接修改参数矩阵,无返回值
def matxRound(M, decPts=4):
    for i in range(len(M)):
        for j in range(len(M[i])):
             M[i][j] = round(M[i][j],decPts)
    pass
# 运行以下代码测试你的 matxRound 函数
%run -i -e test.py LinearRegressionTestCase.test_matxRound

1.4 计算矩阵的转置

# TODO 计算矩阵的转置
def transpose(M):

    return [list(row) for row in zip(*M)]
# 运行以下代码测试你的 transpose 函数
%run -i -e test.py LinearRegressionTestCase.test_transpose

1.5 计算矩阵乘法 AB

# TODO 计算矩阵乘法 AB,如果无法相乘则raise ValueError
def matxMultiply(A, B):
    multiply = []
    if len(A[0]) != len(B):
        raise ValueError
       
    result = [list(row) for row in zip(*B)]

    for Al in range(len(A)):
        row =[]
        for Bl in range(len(result)):
            num = 0   
            for Br in range(len(result[0])):
                num +=  A[Al][Br] * result[Bl][Br]
            row.append(num)
        multiply.append(row)
    return multiply
# 运行以下代码测试你的 matxMultiply 函数
%run -i -e test.py LinearRegressionTestCase.test_matxMultiply

2 Gaussign Jordan 消元法

2.1 构造增广矩阵

 

# TODO 构造增广矩阵,假设A,b行数相同
def augmentMatrix(A, b):
    return [AA + bb for AA, bb in zip(A,b)]
# 运行以下代码测试你的 augmentMatrix 函数
%run -i -e test.py LinearRegressionTestCase.test_augmentMatrix

2.2 初等行变换

  • 交换两行
  • 把某行乘以一个非零常数
  • 把某行加上另一行的若干倍:
    # TODO r1 <---> r2
    # 直接修改参数矩阵,无返回值
    def swapRows(M, r1, r2):
        M[r1],M[r2] = M[r2],M[r1]
        pass
    # 运行以下代码测试你的 swapRows 函数
    %run -i -e test.py LinearRegressionTestCase.test_swapRows
    # TODO r1 <--- r1 * scale
    # scale为0是非法输入,要求 raise ValueError
    # 直接修改参数矩阵,无返回值
    def scaleRow(M, r, scale):
        if scale == 0:
            raise ValueError
        for i in range(len(M[r])):
            M[r][i] *= scale
        pass
    # 运行以下代码测试你的 scaleRow 函数
    %run -i -e test.py LinearRegressionTestCase.test_scaleRow
    # TODO r1 <--- r1 + r2*scale
    # 直接修改参数矩阵,无返回值
    def addScaledRow(M, r1, r2, scale):
        for i in range(len(M[r1])):
            M[r1][i] += M[r2][i] * scale
        pass
    # 运行以下代码测试你的 addScaledRow 函数
    %run -i -e test.py LinearRegressionTestCase.test_addScaledRow

    2.3 Gaussian Jordan 消元法求解 Ax = b

    2.3.1 算法

    步骤1 检查A,b是否行数相同

    步骤2 构造增广矩阵Ab

    步骤3 逐列转换Ab为化简行阶梯形矩阵 中文维基链接

    对于Ab的每一列(最后一列除外)
        当前列为列c
        寻找列c中 对角线以及对角线以下所有元素(行 c~N)的绝对值的最大值
        如果绝对值最大值为0
            那么A为奇异矩阵,返回None (你可以在选做问题2.4中证明为什么这里A一定是奇异矩阵)
        否则
            使用第一个行变换,将绝对值最大值所在行交换到对角线元素所在行(行c) 
            使用第二个行变换,将列c的对角线元素缩放为1
            多次使用第三个行变换,将列c的其他元素消为0
    

    步骤4 返回Ab的最后一列

    注: 我们并没有按照常规方法先把矩阵转化为行阶梯形矩阵,再转换为化简行阶梯形矩阵,而是一步到位。如果你熟悉常规方法的话,可以思考一下两者的等价性。

    2.3.2 算法推演

    为了充分了解Gaussian Jordan消元法的计算流程,请根据Gaussian Jordan消元法,分别手动推演矩阵A为可逆矩阵,矩阵A为奇异矩阵两种情况。

  • 推演有以下要求:

  • 展示每一列的消元结果, 比如3*3的矩阵, 需要写三步
  • 用分数来表示
  • 分数不能再约分
  • 我们已经给出了latex的语法,你只要把零改成你要的数字(或分数)即可
  • 检查你的答案, 可以用这个, 或者后面通过单元测试后的gj_Solve
  • 你可以用python的 fractions 模块辅助你的约分

  • # 不要修改这里!
    from helper import *
    A = generateMatrix(3,seed,singular=False)
    b = np.ones(shape=(3,1),dtype=int) # it doesn't matter
    Ab = augmentMatrix(A.tolist(),b.tolist()) # 请确保你的增广矩阵已经写好了
    printInMatrixFormat(Ab,padding=3,truncating=0)

    请按照算法的步骤3,逐步推演可逆矩阵的变换。

    在下面列出每一次循环体执行之后的增广矩阵。

    要求:

  • 做分数运算
  • 使用\frac{n}{m}来渲染分数,如下:
  • # 不要修改这里!
    A = generateMatrix(3,seed,singular=True)
    b = np.ones(shape=(3,1),dtype=int)
    Ab = augmentMatrix(A.tolist(),b.tolist()) # 请确保你的增广矩阵已经写好了
    printInMatrixFormat(Ab,padding=3,truncating=0)

    请按照算法的步骤3,逐步推演奇异矩阵的变换。

    在下面列出每一次循环体执行之后的增广矩阵。

    要求:

  • 做分数运算
  • 使用\frac{n}{m}来渲染分数,如下:
  • 2.3.3 实现 Gaussian Jordan 消元法

    from decimal import Decimal
    from fractions import Fraction
    # TODO 实现 Gaussain Jordan 方法求解 Ax = b
    
    """ Gaussian Jordan 方法求解 Ax = b.
        参数
            A: 方阵 
            b: 列向量
            decPts: 四舍五入位数,默认为4
            epsilon: 判读是否为0的阈值,默认 1.0e-16
            
        返回列向量 x 使得 Ax = b 
        返回None,如果 A,b 高度不同
        返回None,如果 A 为奇异矩阵
    """
    
    def gj_Solve(A, b, decPts=4, epsilon = 1.0e-16):
        if len(A)!= len(b) :
            return None
    #     构造扩增矩阵
        result = augmentMatrix(A, b)
    #     转换为阶梯型矩阵
        for j in range(len(result[0])-1):
            row,maxNum = 0,0  
            for i in range(len(result)):
                if i >= j:
                    if abs(result[i][j]) > maxNum:
                        maxNum = abs(result[i][j])
                        row = i
    #         返回奇异矩阵
            if(abs(maxNum) < epsilon):
                return None
            else:
    #         找出最大放到最上面
                if(row != j):
                   swapRows(result,j,row)
                   row,maxNum = 0,0 
            scaleRow(result,j,(float(1)/float(result[j][j])))
    #         消除下面  
            for dis in range(len(result)):              
                if dis != j:
                    if abs(-result[dis][j]) > epsilon:
                        addScaledRow(result,dis,j,-result[dis][j])
            newResult =[]
            for i in range(len(result)):
                row =[]
                row.append(result[i][len(result)])
                newResult.append(row)       
        return newResult
    # 运行以下代码测试你的 gj_Solve 函数
    %run -i -e test.py LinearRegressionTestCase.test_gj_Solve

    3 线性回归

  • 3.1 随机生成样本点

    # 不要修改这里!
    # 运行一次就够了!
    from helper import *
    from matplotlib import pyplot as plt
    %matplotlib inline
    
    X,Y = generatePoints(seed,num=100)
    
    ## 可视化
    plt.xlim((-5,5))
    plt.xlabel('x',fontsize=18)
    plt.ylabel('y',fontsize=18)
    plt.scatter(X,Y,c='b')
    plt.show()

    3.2 拟合一条直线

    3.2.1 猜测一条直线

    #TODO 请选择最适合的直线 y = mx + b
    m1 = 3.7
    b1 = 14.6
    
    # 不要修改这里!
    plt.xlim((-5,5))
    x_vals = plt.axes().get_xlim()
    y_vals = [m1*x+b1 for x in x_vals]
    plt.plot(x_vals, y_vals, '-', color='r')
    
    plt.xlabel('x',fontsize=18)
    plt.ylabel('y',fontsize=18)
    plt.scatter(X,Y,c='b')
    
    plt.show()

  • 3.2.2 计算平均平方误差 (MSE)

    我们要编程计算所选直线的平均平方误差(MSE), 即数据集中每个点到直线的Y方向距离的平方的平均数,表达式如下:

    ???=1?∑?=1?(??−???−?)2

    # TODO 实现以下函数并输出所选直线的MSE
    def calculateMSE(X,Y,m,b): 
        return  sum([(y-m*x -b)**2 for x,y in zip(X,Y)])/len(X)
    
    print(calculateMSE(X,Y,m1,b1))

    3.2.3 调整参数 ?,?m,b 来获得最小的平方平均误差

    你可以调整3.2.1中的参数 ?1,?1m1,b1 让蓝点均匀覆盖在红线周围,然后微调 ?1,?1m1,b1 让MSE最小。

    3.3 (选做) 找到参数 ?,?m,b 使得平方平均误差最小

    这一部分需要简单的微积分知识( (?2)′=2?(x2)′=2x )。因为这是一个线性代数项目,所以设为选做。

    刚刚我们手动调节参数,尝试找到最小的平方平均误差。下面我们要精确得求解 ?,?m,b 使得平方平均误差最小。

    定义目标函数 E 为

  • E= 1/2\sum \left ( y-mx-b \right )^2

  •  

    因为 ?=?2???E=n2MSE, 所以 ?E 取到最小值时,???MSE 也取到最小值。要找到 ?E 的最小值,即要找到 ?,?m,b 使得 ?E 相对于 ?m, ?E 相对于 ?b 的偏导数等于0.

    因此我们要解下面的方程组。

    ∂?∂?=0∂?∂?=0{∂E∂m=0∂E∂b=0

     

    3.3.1 计算目标函数相对于参数的导数

    首先我们计算两个式子左边的值

    证明/计算:

    ∂?∂?=∑?=1?−??(??−???−?)∂E∂m=∑i=1n−xi(yi−mxi−b)

    ∂?∂?=∑?=1?−(??−???−?)∂E∂b=∑i=1n−(yi−mxi−b)

     

    TODO 证明:

    3.3.2 实例推演

    现在我们有了一个二元二次方程组

     

    ∑?=1?−??(??−???−?)=0∑?=1?−(??−???−?)=0{∑i=1n−xi(yi−mxi−b)=0∑i=1n−(yi−mxi−b)=0

     

    为了加强理解,我们用一个实际例子演练。

    我们要用三个点 (1,1),(2,2),(3,2)(1,1),(2,2),(3,2) 来拟合一条直线 y = m*x + b, 请写出

  • 目标函数 ?E,
  • 二元二次方程组,
  • 并求解最优参数 ?,?m,b
  • 3.4 求解 ???ℎ=???XTXh=XTY

    在3.3 中,我们知道线性回归问题等价于求解 ???ℎ=???XTXh=XTY (如果你选择不做3.3,就勇敢的相信吧,哈哈)

    TODO 写出目标函数,方程组和最优参数

    3.3.3 将方程组写成矩阵形式

    我们的二元二次方程组可以用更简洁的矩阵形式表达,将方程组写成矩阵形式更有利于我们使用 Gaussian Jordan 消元法求解。

    请证明

    [∂?∂?∂?∂?]=???ℎ−???[∂E∂m∂E∂b]=XTXh−XTY

     

    其中向量 ?Y, 矩阵 ?X 和 向量 ℎh 分别为 :

    ?=?1?2...??,?=?1?2...??11...1,ℎ=[??]Y=[y1y2...yn],X=[x11x21......xn1],h=[mb]

     

    TODO 证明:

    至此我们知道,通过求解方程 ???ℎ=???XTXh=XTY 来找到最优参数。这个方程十分重要,他有一个名字叫做 Normal Equation,也有直观的几何意义。你可以在 子空间投影 和 投影矩阵与最小二乘 看到更多关于这个方程的内容。

  • 3.4 求解 ???ℎ=???XTXh=XTY

    在3.3 中,我们知道线性回归问题等价于求解 ???ℎ=???XTXh=XTY (如果你选择不做3.3,就勇敢的相信吧,哈哈)

    import numpy as np
    '''
    参数:X, Y 存储着一一对应的横坐标与纵坐标的两个一维数组
    返回:m,b 浮点数
    '''
    
    
    def linearRegression(X,Y):
    
        x_num = [[1]] * len(X)  
        newX =augmentMatrix (map(list,zip(X)),x_num) 
        newY = map(list,zip(Y))
        A = matxMultiply (transpose(newX),newX)
        b = matxMultiply(transpose(newX) ,newY)
       
        result =  gj_Solve(A,b,decPts=4,epsilon=1.0e-16)
        print  result[0][0],result[1][0]
        return result[0][0],result[1][0]
    
    m2,b2 =linearRegression(X,Y)
    assert isinstance(m2,float),"m is not a float"
    assert isinstance(b2,float),"b is not a float"
    

    你求得的回归结果是什么? 请使用运行以下代码将它画出来。

  • # 请不要修改下面的代码
    x1,x2 = -5,5
    y1,y2 = x1*m2+b2, x2*m2+b2
    
    plt.xlim((-5,5))
    plt.xlabel('x',fontsize=18)
    plt.ylabel('y',fontsize=18)
    plt.scatter(X,Y,c='b')
    plt.plot((x1,x2),(y1,y2),'r')
    plt.title('y = {m:.4f}x + {b:.4f}'.format(m=m2,b=b2))
    plt.show()
    print(calculateMSE(X,Y,m2,b2))

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习线性代数基础》是一本介绍机器学习与线性代数基础知识的PDF,内容丰富且易于理解。 线性代数是机器学习中必不可少的基础知识之一。它提供了描述和处理向量、矩阵以及线性方程组的工具和方法。《机器学习线性代数基础》这本PDF详细介绍了线性代数的相关概念和方法,并结合机器学习的应用场景进行说明和实践。 PDF的内容主要包括以下几个方面: 1. 向量和矩阵的基本概念和运算:介绍了向量和矩阵的定义、加法、乘法等基本运算,以及线性相关性的判定等内容。 2. 矩阵的分解:介绍了特征值和特征向量、奇异值分解等矩阵的分解方法,以及它们在机器学习中的应用。 3. 线性变换和线性方程组:讲解了线性变换和线性方程组的相关概念和求解方法,以及它们在机器学习中的应用。 4. 向量空间和基底:介绍了向量空间的概念、基底和维数的定义,以及它们在机器学习中的应用。 5. 线性代数在机器学习中的应用:通过实际的机器学习案例,展示线性代数在特征选择、降维、回归分析等问题中的应用。 这本PDF适合初学者和对线性代数和机器学习感兴趣的人阅读。通过学习《机器学习线性代数基础》,可以帮助读者建立起对线性代数的基本理解和应用能力,并为进一步深入学习机器学习打下坚实的数学基础。总而言之,这本PDF是学习机器学习和线性代数的一本很好的参考资料。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值