機器學習——線性回歸算法


一、線性回歸問題

1、線性回歸問題介紹

(1)示例介紹

  數據:工資和年齡(2個特征)

  目標:預測銀行會貸款多少錢(標簽)

  考慮:工資和年齡都會影響最終銀行貸款的結果,那么它們各自有多大的影響?(參數)

   

  通過圖表可以看出隨着工資和年齡的增長,貸款額度也隨之增長。X1和X2的數量級是不同的,因此需要增加兩個因子:θ1x12x2=y ,在已知x1,x2,y的情況下建立回歸方程。方程的目標就是求出最合適的θ1、θ2,這樣就知道工資和年齡對貸款額度到底有多大的影響。

(2)通俗解釋

  X1、X2就是我們的兩個特征(年齡、工資),Y是銀行最終會借給我們多少錢。

  找到最合適的一條線(想象一個高維)來最好的擬合我們的數據點。(無法滿足所有,滿足盡可能多的點)

  

  圖中紅點是樣本數據,想根據給定的數據集擬合一個平面,使得各個樣本數據到達平面的誤差最小。

  這個圖就是機器如何進行預測的(回歸)它會根據貸款的歷史數據(年齡和工資分別對應於X1與X2)找出來最好的擬合線(面)來進行預測,這樣新的數據來了之后直接帶入進去就可以得出來該給多少錢了。

(3)進一步整合回歸方程

  整合是把偏置項和權重參數項放到了一起(加了個θ0讓其都等於1)。

  • 假設θ1是年齡的參數,θ2是工資的參數。
  • 擬合的平面:hθ(x) = θ0 + θ1x1 + θ2x2 。參數θ1、θ2為權重項,對結果影響較大。θ0是偏置項
  • 整合:

2、偏置項理解

  一個傳統的神經網絡就可以看成多個邏輯回歸模型的輸出作為另一個邏輯回歸模型的輸入的“組合模型”。

  因此,討論神經網絡中的偏置項b的作用,就近似等價於討論邏輯回歸模型中的偏置項b的作用。

(1)邏輯回歸偏置項

  邏輯回歸模型本質:利用 y = WX + b 這個函數畫決策面,其中W為模型參數,也是函數的斜率;b為函數的截距。

  一維情況:W=[1],b=2,y=WX+b得到一個截距為2,斜率為1的直線如下所示:

  

  二維情況:W=[1 1],b=2,則 y=WX+b得到一個截距為2,斜率為[1 1]的平面如下所示:

  

  顯然y=WX+b這個函數,就是2維/3維/更高維空間的直線/平面/超平面。如果沒有偏置項b,則只能在空間里畫過原點的直線/平面/超平面。

  因此對於邏輯回歸必須加上偏置項b,才能保證分類器可以在空間任何位置畫決策面。

(2)神經網絡偏置項

  同理,對於多個邏輯回歸組成的神經網絡,更要加上偏置項b。

  如果隱層有3個節點,那就相當於有3個邏輯回歸分類器。這三個分類器各畫各的決策面,那一般情況下它們的偏置項b也會各不相同。

  復雜決策邊界由三個隱層節點的神經網絡畫出如下:

  

  如何機智的為三個分類器(隱節點)分配不同的b呢?或者說如果讓模型在訓練的過程中,動態的調整三個分類器的b以畫出各自最佳的決策面呢?

  那就是先在X的前面加個1,作為偏置項的基底,(此時X就從n維向量變成了n+1維向量,即變成 [1, x1,x2…] ),然后,讓每個分類器去訓練自己的偏置項權重,所以每個分類器的權重就也變成了n+1維,即[w0,w1,…],其中,w0就是偏置項的權重,所以1*w0就是本分類器的偏置/截距啦。這樣,就讓截距b這個看似與斜率W不同的參數,都統一到了一個框架下,使得模型在訓練的過程中不斷調整參數w0,從而達到調整b的目的。

  所以,如果在寫神經網絡的代碼的時候,把偏置項給漏掉了,那么神經網絡很有可能變得很差,收斂很慢而且精度差,甚至可能陷入“僵死”狀態無法收斂。

3、誤差項定義

  銀行的目標得讓誤差越小越好,這樣才能夠使得我們的結果是越准確的。

  • 真實值和預測值之間肯定要存在差異——用 ε 來表示該誤差。
  • 對於每個樣本:y(i) = θTx(i) + ε(i) y(i)是真實值,θTx(i)是預測值, ε(i)是差異值
  • 每一個樣本的誤差值是不同的:

  

4、誤差規律——獨立同分布

  獨立同分布(iid,independently identically distribution)在概率統計理論中,指隨機過程中,任何時刻的取值都為隨機變量,如果這些隨機變量服從同一分布,並且互相獨立,那么這些隨機變量是獨立同分布。

  • 誤差ε(i)是獨立且具有相同分布,並且服從均值為0方差為θ2的高斯分布;
  • 獨立:張三和李四一起來貸款,他倆沒有關系,即每個樣本到擬合平面的距離都不相同;
  • 同分布:他倆都來得是我們假定的同一家銀行,所以它在預測的時候是按照同樣的方式,數據是在同一個分布下去建模,盡可能來自相同的分布;
  • 高斯分布:銀行可能會多給,也可能會少給,但是絕大多數情況下,這個浮動不會太大,極小情況下浮動會比較大(有的多有的少,大概來看,均值為0)。

  

   誤差在0附近浮動的可能性較大,正負差距較大的可能性越來越小。符合概率統計中現實分布情況。

  

  將(1)式轉化為:ε(i) = y(i) - θTx(i) ,即:誤差=實際值-預測值,然后帶入高斯分布函數(2)式,就將誤差項都替換為了x,y。

  p(x;θ)代表:在給定θ的情況下x的取值;

  p(y|x;θ)代表:在給定x的情況下,還給定某種參數θ的情況下,y的概率密度函數。

  由於x和θ是一個定值,所以θTx(i) 可以理解為一個定值C。

5、似然函數

  似然函數是一種關於模型中參數的函數,用來表示模型參數中的似然性

  已知樣本數據x(x1,x2,...,xn)組合,要使用什么樣的參數θ和樣本數據組合后,可以恰好得到真實值

  要讓誤差項越小越好,則要讓似然函數越大越好,由此將問題轉為求L(θ)的最大值。

(1)引入似然函數

  引入似然函數如下:(Π從...到...的積)

  

  連續型變量相互獨立的充要條件是聯合概率密度等於邊緣概率密度的乘積。因此變量符合獨立同分布前提下,聯合概率密度等於邊緣概率密度的乘積成立。

  p(y(i) | x(i);θ):什么樣的x和θ組合完后,能成為y的可能性越大越好。m項的乘積非常難解,難以估計,因此要想辦法轉為加法。

  對數似然:乘法難解,加法相對容易,對數里面乘法可以轉換成加法,因此對式子左右兩邊取對數。

  log(AB) = logA + logB

  

(2)為什么取對數?

  首先,取對數不影響函數的單調性,保證輸入對應的概率的最大最小值對應似然函數的最值。

  其次,減少計算量,比如聯合概率的連乘會變成加法問題,指數亦可。

  最后,概率的連乘將會變成一個很小的值,可能會引起浮點數下溢,尤其是當數據集很大的時候,聯合概率會趨向於0,非常不利於之后的計算。依據ln曲線可知,很小的概率(越接近0)經過對數轉換會轉變為較大的負數,解決下溢問題。

  取對數雖然會改變極值,但不會改變極值點。任務依然是求極值,因此L(θ)和logL(θ)兩者是等價的。

6、參數求解

(1)公式繼續展開化簡

  繼續處理: ,由於log A·B = logA + logB,因此可以將累乘轉換為累加:

  進一步觀察發現,可以將上面的式子看作是 和  兩部分的組合,即log A·B = logA + logB。

  這里要求解是的 θ,因此其他的都可以看作是常數項。 因此可以把看作是m倍的常數項:

  再觀察另一個部分:,exp:高等數學里以自然常數e為底的指數函數,它同時又是航模名詞,全稱Exponential(指數曲線)。由於給對數取不同的底數只會影響極值,但不會影響極值點。 

  將這一部分底數取e,則與exp(x)的以e為底的指數發生抵消,再將常數項提取出來,可以將公司轉成這種累加形式:

  公式到這里就不能繼續化簡了,畢竟每個人的年齡(x)和每個有多少錢(y)是不同的,因此,必須從第一個樣本迭代到第m個樣本。最終簡化為:

(2)目標:讓似然函數越大越好

  之前的目標:x和θ組合完后,成為y的可能性越大越好。因此現在要求得極大值點。A是一個恆為正的常數,B中包含平分因此也是一個正數。因此是兩個正數間的減法。

  如要求值越大越好,因此B:必須越小越好。

  現在就將目標轉換為求解最小二乘法

二、求解最小二乘法

  從上面的推導可以得出結論:要求讓似然函數越大越好,可轉化為求θ取某個值時使J(θ)最小的問題。

  

 

  求解最小二乘法的方法一般為兩種:矩陣式梯度下降法

1、矩陣式求解

  數據集含有m個樣本,每個樣本有n個特征時:

  • 數據x可以寫成m*(n+1)維的矩陣(+1是添加一列1,用於與截斷b相乘);
  • θ則為n+1維的列向量(+1是截斷b);
  • y為m維的列向量代表每m個樣本結果的預測值。

  矩陣式的推導如下所示:

   

  讓J(θ)對θ求偏導,當偏導等於零時,則這個θ就是極值點。XT代表X矩陣的轉置,XT與X的乘積一定會得到一個對稱陣。

  另外存在公式: θTXTXθ 等於 2XTXθ。

  XTX的逆矩陣為:(XTX)-1 ,將這個逆矩陣分別乘到偏導結果等式兩邊,左邊期望是零,推導得到:

  0 = θ - (XTX)-1 · XTy,轉換等式得到:θ=(XTX)-1XTy

  這種方法存在的問題:不存在學習的過程;矩陣求逆不是一個必然成功的行為(存在不可逆);

2、梯度下降法(GD)

  目標函數:

  對於多元線性回歸來說,擬合函數為:

  由於目標函數是由m個樣本累加得到的,因此可以求一個平均得到損失函數:

  1)對損失函數求偏導數,批量梯度下降:

  

  容易得到最優解,但是每次考慮所有樣本,執行速度很慢。

  2)每次只用一個樣本,隨機梯度下降:

  

  去除累加操作,每次抽樣一個樣本來計算,速度快,結果不准。

  3)每次更新選擇一部分數據,小批量梯度下降法:

  

(1)為什么要使用梯度下降

  當得到一個目標函數時,通常是不能直接求解的,線性回歸能求出結果在機器學習中是一個特例。

  機器學習常規套路:交給機器一堆數據,然后告訴它使用什么樣的學習方式(目標函數),然后它朝着這個方向去學習。

  算法優化:一步步完成迭代,每次優化一點點,積累起來就能獲得大成功。

(2)梯度概念

  在一元函數中叫做求導,在多元函數中就叫做求梯度。梯度下降是一個最優化算法,通俗的來講也就是沿着梯度下降的方向來求出一個函數的極小值。比如一元函數中,加速度減少的方向,總會找到一個點使速度達到最小。

  通常情況下,數據不可能完全符合我們的要求,所以很難用矩陣去求解,所以機器學習就應該用學習的方法,因此我們采用梯度下降,不斷迭代,沿着梯度下降的方向來移動,求出極小值。

  梯度下降法包括批量梯度下降法和隨機梯度下降法(SGD)以及二者的結合mini批量下降法(通常與SGD認為是同一種,常用於深度學習中)。

(3)梯度下降法實驗

  對於梯度下降,我們可以形象地理解為一個人下山的過程。假設現在有一個人在山上,現在他想要走下山,但是他不知道山底在哪個方向,怎么辦呢?顯然我們可以想到的是,一定要沿着山高度下降的地方走,不然就不是下山而是上山了。山高度下降的方向有很多,選哪個方向呢?這個人比較有冒險精神,他選擇最陡峭的方向,即山高度下降最快的方向。現在確定了方向,就要開始下山了。

  又有一個問題來了,在下山的過程中,最開始選定的方向並不總是高度下降最快的地方。這個人比較聰明,他每次都選定一段距離,每走一段距離之后,就重新確定當前所在位置的高度下降最快的地方。這樣,這個人每次下山的方向都可以近似看作是每個距離段內高度下降最快的地方。

  現在我們將這個思想引入線性回歸,在線性回歸中,我們要找到參數矩陣 [公式] 使得損失函數 [公式] 最小。如果把損失函數 [公式] 看作是這座山,山底不就是損失函數最小的地方嗎,那我們求解參數矩陣 [公式] 的過程,就是人走到山底的過程。

  

  如圖所示,這是一元線性回歸(即假設函數 [公式] )中的損失函數圖像,一開始我們選定一個起始點(通常是 [公式] ),然后沿着這個起始點開始,沿着這一點處損失函數下降最快的方向(即該點的梯度負方向)走一小步,走完一步之后,到達第二個點,然后我們又沿着第二個點的梯度負方向走一小步,到達第三個點,以此類推,直到我們到底局部最低點。為什么是局部最低點呢?因為我們到達的這個點的梯度為 0 向量(通常是和 0 向量相差在某一個可接受的范圍內),這說明這個點是損失函數的極小值點,並不一定是最小值點。 

  

  從梯度下降法的思想,我們可以看到,最后得到的局部最低點與我們選定的起始點有關。通常情況下,如果起始點不同,最后得到的局部最低點也會不一樣。

(4)參數更新 

  每次更新參數的操作:

  

  其中α學習率(步長),對結果會產生巨大的影響,調節學習率這個超參數是建模中的重要內容。

  選擇方法:從小的開始,不行再小。

  批處理數量:32、64、128比較常用,很多時候還要考慮內存和效率。

  

  因為J(θ)是凸函數,所以GD求出的最優解是全局最優解。批量梯度下降法是求出整個數據集的梯度,再去更新θ,所以每次迭代都是在求全局最優解。

三、單特征回歸建模

1、數據預處理

  寫一個prepare_for_training函數,對數據進行函數變換、標准化等操作。最后返回處理過的數據,以及均值和標准差。

import numpy as np
from .normalize import normalize
from .generate_sinusoids import generate_sinusoids
from .generate_polynomials import generate_polynomials


"""數據預處理"""
def prepare_for_training(data, polynomial_degree=0, sinusoid_degree=0, normalize_data=True):

    # 計算樣本總數
    num_examples = data.shape[0]

    data_processed = np.copy(data)

    # 預處理
    features_mean = 0
    features_deviation = 0
    data_normalized = data_processed
    if normalize_data:
        (
            data_normalized,
            features_mean,
            features_deviation
        ) = normalize(data_processed)

        data_processed = data_normalized

    # 特征變換sinusoid
    if sinusoid_degree > 0:
        sinusoids = generate_sinusoids(data_normalized, sinusoid_degree)
        data_processed = np.concatenate((data_processed, sinusoids), axis=1)

    # 特征變換polynomial
    if polynomial_degree > 0:
        polynomials = generate_polynomials(data_normalized, polynomial_degree)
        data_processed = np.concatenate((data_processed, polynomials), axis=1)

    # 加一列1
    data_processed = np.hstack((np.ones((num_examples, 1)), data_processed))

    return data_processed, features_mean, features_deviation

2、線性回歸模塊

  寫一個LinearRegression類,包含線性回歸相關的方法。

import numpy as np
from utils.features.prepare_for_training import prepare_for_training

"""線性回歸"""
class LinearRegression:
    def __init__(self, data, labels, polynomial_degree=0, sinusoid_degree=0, normalize_data=True):
        """
        1.對數據進行預處理操作
        2.先得到所有的特征個數
        3.初始化參數矩陣
        """
        (data_processed, features_mean, features_deviation) = prepare_for_training(data, polynomial_degree, sinusoid_degree)

        self.data = data_processed
        self.labels = labels
        self.features_mean = features_mean
        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]    # 1是列個數,0是樣本個數
        self.theta = np.zeros((num_features, 1))   # 構建θ矩陣

    def train(self, alpha, num_iterations=500):
        """
        訓練模塊,執行梯度下降
        :param alpha: α為學習率(步長)
        :param num_iterations: 迭代次數
        :return:
        """
        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 _ 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
        # theta值更新,.T是執行轉置
        theta = theta - alpha * (1/num_examples)*(np.dot(delta.T, self.data)).T
        self.theta = theta

    def cost_function(self, data, labels):
        """
        損失計算
        :param data: 數據集
        :param labels: 真實值
        :return:
        """
        num_examples = data.shape[0]       # 樣本個數
        # 參差=預測值-真實值
        delta = LinearRegression.hypothesis(self.data, self.theta) - labels
        cost = (1/2)*np.dot(delta.T, delta)
        print(cost.shape)
        print(cost)
        return cost[0][0]

    @staticmethod
    def hypothesis(data, theta):
        """
        預測函數
        :param data:
        :param theta:
        :return:
        """
        # 如果處理的是一維數組,則得到的是兩數組的內積;如果處理的是二維數組(矩陣),則得到的是矩陣積
        predictions = np.dot(data, theta)
        return predictions

    def get_cost(self, data, labels):
        """
        計算當前損失
        :param data:
        :param labels:
        :return:
        """
        # 經過處理了的數據
        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      # 返回預測值

3、訓練線性回歸模型

  對 LinearRegression類進行建模、預測、計算損失等。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from linear_regression import LinearRegression

"""單變量線性回歸"""

data = pd.read_csv('../data/world-happiness-report-2017.csv')

# 得到訓練和測試數據集
train_data = data.sample(frac = 0.8)      # sample:隨機選取若干行
test_data = data.drop(train_data.index)   # 將訓練數據刪除即為測試數據

# 數據和標簽定義
input_param_name = "Economy..GDP.per.Capita."
output_param_name = "Happiness.Score"

x_train = train_data[[input_param_name]].values
y_train = train_data[[output_param_name]].values

x_test = test_data[[input_param_name]].values
y_test = test_data[[output_param_name]].values

plt.scatter(x_train, y_train, label="Train data")
plt.scatter(x_test, y_test, label="Test data")
plt.xlabel(input_param_name)
plt.ylabel(output_param_name)
plt.title('Happy')     # 指定名字
plt.legend()
plt.show()

# 訓練線性回歸模型
num_iterations = 500
learning_rate = 0.01     # 學習率

linear_regression = LinearRegression(x_train, y_train)   # 線性回歸
(theta, cost_history) = linear_regression.train(learning_rate, num_iterations)    # 執行訓練

print('開始時的損失', cost_history[0])
print('訓練后的損失', cost_history[-1])   # 最后一個

plt.plot(range(num_iterations), cost_history)
plt.xlabel('Iteration')
plt.ylabel('Cost')
plt.title('GD')
plt.show()

# 測試
predications_num = 100
x_predications = np.linspace(x_train.min(), x_train.max(), predications_num).reshape(predications_num,1)
y_predications = linear_regression.predict(x_predications)

plt.scatter(x_train, y_train, label="Train data")
plt.scatter(x_test, y_test, label="Test data")
plt.plot(x_predications, y_predications, 'r', label="預測值")
plt.xlabel(input_param_name)
plt.ylabel(output_param_name)
plt.title("Happy test")
plt.legend()
plt.show()

  運行結果如下:

  開始時的損失 1791.3527192463505
  訓練后的損失 26.382344732117332

  輸出圖表:

  

   損失值:

  

  線性回歸方程:

  

四、多特征回歸模型

  多特征建模,觀察與單特征建模效果對比。

1、plotly工具包

  Plotly 是一款用來做數據分析和可視化的在線平台,功能非常強大,可以在線繪制很多圖形比如條形圖、散點圖、餅圖、直方圖等等。而且還是支持在線編輯,以及多種語言python、javascript、matlab、R等許多API。使用Plotly可以畫出很多媲美Tableau的高質量圖:

  導入庫:
from plotly.graph_objs import Scatter,Layout
import plotly
import plotly.offline as py
import numpy as np
import plotly.graph_objs as go

#setting offilne
plotly.offline.init_notebook_mode(connected=True)

  制作散點圖:

trace1 = go.Scatter(
     y = np.random.randn(500),
    mode = 'markers',
    marker = dict(
        size = 16,
        color = np.random.randn(500),
        colorscale = 'Viridis',
        showscale = True
    )
)
data = [trace1]
py.iplot(data)

  把mode設置為markers就是散點圖,然后marker里面設置一組參數,比如顏色的隨機范圍,散點的大小,還有圖例等等。

  推薦最好在jupyter notebook中使用,pycharm操作不是很方便。

2、代碼實現

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import plotly   # 交互式界面展示
import plotly.graph_objs as go
plotly.offline.init_notebook_mode()
from linear_regression import LinearRegression

"""單變量線性回歸"""

data = pd.read_csv('../data/world-happiness-report-2017.csv')

# 得到訓練和測試數據集
train_data = data.sample(frac = 0.8)      # sample:隨機選取若干行
test_data = data.drop(train_data.index)   # 將訓練數據刪除即為測試數據

# 數據和標簽定義
input_param_name_1 = "Economy..GDP.per.Capita."
input_param_name_2 = "Freedom"
output_param_name = "Happiness.Score"

x_train = train_data[[input_param_name_1, input_param_name_2]].values
y_train = train_data[[output_param_name]].values

x_test = test_data[[input_param_name_1, input_param_name_2]].values
y_test = test_data[[output_param_name]].values

# 訓練集
plot_training_trace = go.Scatter3d(
    x=x_train[:, 0].flatten(),
    y=x_train[:, 1].flatten(),
    z=y_train.flatten(),
    name="Training Set",
    mode="markers",
    marker={
        'size': 10,
        'opacity': 1,
        'line': {
            'color': 'rgb(255, 255, 255)',
            'width': 1
        }
    }
)

# 測試集
plot_test_trace = go.Scatter3d(
    x=x_test[:, 0].flatten(),
    y=x_test[:, 1].flatten(),
    z=y_test.flatten(),
    name="Test Set",
    mode="markers",
    marker={
        'size': 10,
        'opacity': 1,
        'line': {
            'color': 'rgb(255, 255, 255)',
            'width': 1
        }
    }
)

# 布局
plot_layout = go.Layout(
    title = 'Date Sets',
    scene = {
        'xaxis': {'title': input_param_name_1},
        'yaxis': {'title': input_param_name_2},
        'zaxis': {'title': output_param_name}
    },
    margin={'l': 0, 'r': 0, 'b': 0, 't': 0}
)

plot_data = [plot_training_trace, plot_test_trace]

plot_figure = go.Figure(data=plot_data, layout=plot_layout)

plotly.offline.plot(plot_figure)    # 彈出瀏覽器網頁展示

num_iterations = 500
learning_rate = 0.01     # 學習率
polynomial_degree = 0
sinusoid_degree = 0

linear_regression = LinearRegression(x_train, y_train, polynomial_degree, sinusoid_degree)

(theta, cost_history) = linear_regression.train(
    learning_rate,
    num_iterations
)

print('開始損失', cost_history[0])
print('結束損失', cost_history[-1])

plt.plot(range(num_iterations), cost_history)
plt.xlabel('Iterations')
plt.ylabel('Cost')
plt.title('Gradient Descent Progress')
plt.show()

predictions_num = 10

x_min = x_train[:, 0].min()
x_max = x_train[:, 0].max()

y_min = x_train[:, 1].min()
y_max = x_train[:, 1].max()

x_axis = np.linspace(x_min, x_max, predictions_num)
y_axis = np.linspace(y_min, y_max, predictions_num)

x_predictions = np.zeros((predictions_num * predictions_num, 1))
y_predictions = np.zeros((predictions_num * predictions_num, 1))

x_y_index = 0
for x_index, x_value in enumerate(x_axis):
    for y_index, y_value in enumerate(y_axis):
        x_predictions[x_y_index] = x_value
        y_predictions[x_y_index] = y_value
        x_y_index += 1

z_predictions = linear_regression.predict(np.hstack((x_predictions, y_predictions)))

plot_predictions_trace = go.Scatter3d(
    x=x_predictions.flatten(),
    y=y_predictions.flatten(),
    z=z_predictions.flatten(),
    name='Prediction Plane',
    marker={
        'size': 1,
    },
    opacity=0.8,
    surfaceaxis=2
)

plot_data = [plot_training_trace, plot_test_trace, plot_predictions_trace]
plot_figure = go.Figure(data=plot_data, layout=plot_layout)
plotly.offline.plot(plot_figure)

  展示結果:

  

五、非線性回歸模型

"""非線性回歸"""

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from linear_regression import LinearRegression

data = pd.read_csv('../data/non-linear-regression-x-y.csv')

x = data['x'].values.reshape((data.shape[0], 1))
y = data['y'].values.reshape((data.shape[0], 1))

data.head(10)

# visualize the training and test datasets to see the shape of the data
plt.plot(x, y)
plt.show()

# Set up linear regression parameters.
num_iterations = 50000
learning_rate = 0.02
polynomial_degree = 15   # The degree of additional polynomial features.
sinusoid_degree = 15     # The degree of sinusoid parameter multipliers of additional features.
normalize_date = True

# Init linear regression instance.
# linear_regression = LinearRegression(x, y, normalize_date)   # 線性回歸
linear_regression = LinearRegression(x, y, polynomial_degree, sinusoid_degree, normalize_date)

# Train linear regression
(theta, cost_history) = linear_regression.train(
    learning_rate,
    num_iterations
)

print('開始損失: {:.2f}'.format(cost_history[0]))
print('結束損失: {:.2f}'.format(cost_history[-1]))

theta_table = pd.DataFrame({'Model Parameters': theta.flatten()})

# Plot gradient descent progress.
plt.plot(range(num_iterations), cost_history)
plt.xlabel('Iterations')
plt.ylabel('Cost')
plt.title('Gradient Descent Progress')
plt.show()

# Get model predictions for the trainint set.
predictions_num = 1000
x_predictions = np.linspace(x.min(), x.max(), predictions_num).reshape(predictions_num,1)
y_predictions = linear_regression.predict(x_predictions)

# Plot training data with predictions.
plt.scatter(x, y, label='Training Dataset')
plt.plot(x_predictions, y_predictions, 'r', label='Prediction')
plt.show()

  執行效果:

  開始損失: 580629.11

  結束損失: 8777.68

  

  非線性回歸方程:

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM