3、线性回归(解析法和梯度下降法)

import random as rd
import matplotlib.pyplot as plt
import functools
import math
import numpy as np

def sample_generate(n, low, sup, w, e):
    X = [[(sup-low) * rd.random() + low if j < len(w)-1 else 1 for j in range(len(w))] for i in range(n)]
    Y = [sum([w[j]*X[i][j] for j in range(len(w))])+e*(rd.random()-0.5) for i in range(n)]
    return X,Y

def inv_calculate(X, Y):

    n = len(X)
    X = np.mat(X)
    Y = np.mat([[Y[i]] for i in range(len(Y))])
    w = np.linalg.inv(X.T*X)*X.T*Y
    w = w.tolist()
    return [w[i][0] for i in range(len(w))]

def LR_2_plot(X, Y, k, b):

    X = [X[i][0] for i in range(len(X))]

    x0, x1 = min(X),max(X)
    y0, y1 = k*x0+b, k*x1+b
    #点、线展示
    plt.scatter(X, Y)
    plt.plot([x0,x1], [y0,y1], color = 'r')
    plt.show()

def f(w, X, Y):
    return (w.T*X.T*X*w - 2*Y.T*X*w)[0,0]

def mod(dw):
    return math.sqrt(sum([dw[i,0]*dw[i,0] for i in range(dw.size)]))

# r为放缩尺度, step_min为最小步长
def Gradient(X, Y, r = 0.8, step_min = 0.00001):
    d = len(X[0])
    X = np.mat(X)
    Y = np.mat([[Y[i]] for i in range(len(Y))])
    w = [[0] for i in range(d)]
    w = np.mat(w)

    # 先采用放缩法确定寻优区间
    while True:
        left = 0
        right = 1
        dw = -X.T * X * w + X.T * Y
        while f(w+right*dw, X, Y) < f(w, X, Y):
            right = right*(2-r)

        mid1 = left*2/3 + right/3
        mid2 = left/3 + right*2/3
        while abs(left - right)*mod(dw) > step_min:
            if f(w+mid1*dw, X, Y) < f(w+mid2*dw, X, Y):
                right = mid2
            else:
                left = mid1
            mid1 = left * 2 / 3 + right / 3
            mid2 = left / 3 + right * 2 / 3

        if left*mod(dw) < step_min:
            break
        w = w + left * dw


    # 由二分法确定寻优步长

    w = w.tolist()
    return [w[i][0] for i in range(len(w))]


if __name__ == "__main__":

    # y = wTx
    X, Y = sample_generate(n = 100, low = 10, sup = 20, w = [2,3,4], e = 1)

    # 解析解,求逆得到, w = (X.T*X)-1 * X.T * Y
    # w = inv_calculate(X,Y)
    # print("\nk: ", w[0])
    # print("\nb: ", w[1])
    # LR_2_plot(X, Y, w[0], w[1])

    # 梯度下降法
    w = Gradient(X, Y)
    print("\nw: ", w)
    # print("\nk: ", w[0])
    # print("\nb: ", w[1])
    # LR_2_plot(X, Y, w[0], w[1])

 

你可能感兴趣的:(3、线性回归(解析法和梯度下降法))