###### tags: `Machine Learning`,`Rregression`,`multiple regression`
# Machine Learning 基礎篇-Linear Rregression,Multiple Regression


* 機器學習演算法是一種從資料中學習,不需要人類干預,就可以自從資料中取得經驗,並且從經驗提升能力的演算法。
* 機器學習理論主要是設計和分析一些讓電腦可以自動「學習」的演算法。
* 機器學習演算法是一類從資料中自動分析獲得規律,並利用規律對未知資料進行預測的演算法。
* 機器學習已廣泛應用於資料探勘、電腦視覺、自然語言處理、生物特徵辨識、搜尋引擎、醫學診斷、檢測信用卡欺詐、證券市場分析、DNA序列定序、語音和手寫辨識、戰略遊戲和機器人等領域。
* 監督式學習(給予答案):
1. 回歸問題:預測連續的回應資料,例如:預測商店的營業額、學生的身高和體重.
常用的演算法有線性回歸(Rregression)、SVR。
2. 分類問題: 預測可分類的回應資料,這是一些有限集合,例如:分類男生與女生、是或否、癌症分類1到4期、喜愛程度(1到5級別)等。
常用的演算法:Logistic回歸、決策樹、K鄰近演算法、CART、樸素被葉斯等。
* 非監督式學習(沒有答案):
1. 分群:將樣本分成相似的群組,可以分群初喜歡同一類電影的觀眾,常用演算法:K-means演算法。
2. 降維:減少資料集中變數的個數,但仍保留主要資料不失真,通常使用特徵提取和選擇方法來實作,常用演算法有:主成份分析演算法。
下圖來源:scikit-learn官方圖,各式演算法

**線性回歸**
在統計學中,線性迴歸(英語:linear regression)是利用稱為線性迴歸方程式的最小平方函數對一個或多個自變數和應變數之間關係進行建模的一種迴歸分析。這種函數是一個或多個稱為迴歸係數的模型參數的線性組合。只有一個自變數的情況稱為簡單迴歸,大於一個自變數情況的叫做多元迴歸(multivariable linear regression)。

* 回歸線的斜率是正值(右上左下直線):代表x,y為正相關,x值增加,y值也跟著增加。
* 回歸線的斜率是負值(左上右下直線):代表x,y為負相關,x值減少,y值反而是增加。
**簡單線性回歸**
* 只有一個解釋變數,這條線可以使用數學上的一次方程式來表示:
y = a + bX
y:反應變數(Response)或稱應變數
X:解釋變數(Explanatory)或稱自變數
a:截距(Intercept)
b:迴歸係數(coefficients)


==導入例題sample1==
推算不同氣溫下的日營業額(千元)
| 氣溫 | 29 | 28 | 34 | 31 | 25 | 29 | 32 | 31 | 24 | 33 | 25 | 31 | 26 | 30 |
| ----- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 營業額 | 7.7 | 6.2 | 9.3 | 8.4 | 5.9 | 6.4 | 8.0 | 7.5 | 5.8 | 9.1 | 5.1 | 7.3 | 6.5 | 8.4 |
```python
# 1. 匯入套件
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
# 2. 設定來源資料
temp = np.array([29,28,34,31,25,29,32,31,24,33,25,31,26,30])
price = np.array([7.7,6.2,9.3,8.4,5.9,6.4,8.0,7.5,5.8,9.1,5.1,7.3,6.5,8.4])
X = pd.DataFrame(temp, columns=["Temperature"])
y = pd.DataFrame(price, columns=["Sale Price"])
#################################
# 1. 匯入套件
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
# 2. 設定來源資料
#np.array為一維格式(從左到右)
temp = np.array([29,28,34,31,25,29,32,31,24,33,25,31,26,30])
sales = np.array([7.7,6.2,9.3,8.4,5.9,6.4,8.0,7.5,5.8,9.1,5.1,7.3,6.5,8.4])
##一般約定熟成自變數會帶大寫的X,應變數帶小寫的y
#DataFrame將資料轉換成2維格式(資料格式變成從上到下)
X = pd.DataFrame(temp, columns=["Temperature"])
y = pd.DataFrame(sales, columns=["Sale Price"])
# 3. 建立模型(建立演算法物件,lm 代表:LinearRegression Model簡寫)
lm = LinearRegression()
lm.fit(X, y) #fit表示丟進模型進行學習
print("迴歸係數:",lm.coef_) #coef_是屬性,迴歸係數: [[0.37378855]]
print("截距:",lm.intercept_) #intercept_是屬性,截距: [-3.63612335]
# 4. 進行預測 氣溫26,30度的業績
#預估值的資料格式要跟建立的資料格式一樣
#當初用2維的資料型態去建立演算法,如要預估資料型態也必須符合2維的資料型態
new_temp = pd.DataFrame(np.array([26,30]),columns=["Temperature"])
predicted_price = lm.predict(new_temp)#將新的值拿去做銷售預估
print(predicted_price) #[[6.08237885][7.57753304]] 即為銷售預估值
plt.scatter(temp,sales)
regression_price = lm.predict(X)
plt.plot(temp,regression_price,color="blue")
plt.scatter(new_temp,predicted_price,color="red",marker="o")
plt.show()
```


==sample2==
```python=
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
#設定來源資料
heigh = np.array([147,163,159,155,163,158,172,161,153,161])
weight = np.array([41,60,47,53,48,55,58.5,49,46,52.5])
X = pd.DataFrame(heigh, columns=["Heigh"])
y = pd.DataFrame(weight, columns=["Weight"])
lm = LinearRegression()
lm.fit(X, y) #y代表要預估的值
print("*************1st************")
#題目:進行身高155,165,180的體重預估
#預估值的資料格式要跟建立的資料格式一樣
new_heigh_np = np.array([155,165,180])
new_heigh = pd.DataFrame(new_heigh_np,columns=["Heigh"])
predicted_weight = lm.predict(new_heigh)
predicted_weight = predicted_weight.round(1)
for i in range(3):
print("Hieght:{} cm ,predicted: {} kg".format(new_heigh_np[i],predicted_weight[i]))
print("1st.迴歸係數:",lm.coef_)
print("1st.截距:",lm.intercept_)
#############################################
#題目:進行體重55.65.70,預測其身高
lm.fit(y,X)
print("*************2nd************")
new_weight_np = np.array([55,65,70])
new_weight = pd.DataFrame(new_weight_np,columns=["Weight"])
predicted_height = lm.predict(new_weight)
predicted_height = predicted_height.astype(np.int16)
for i in range(3):
print("Weight:{} kg ,predicted: {} cm".format(new_weight_np[i],predicted_height[i]))
print("2nd.迴歸係數:",lm.coef_)
print("2nd.截距:",lm.intercept_)
```


**複回歸-multiple regression analysis**
* 複迴歸(也稱:多元迴歸)是用來探討一個應變數和多個自變數的關係
* 多因1果的呈現
* Python程式只需將原來解釋變數的DataFrame物件X從1個欄位擴充成多個欄位,每一個欄位是一個解釋變數
* 簡單迴歸表示式:
Y = β0 +β1X1 + ε
β0 為常數,β 1為迴歸係數,ε 為誤差
* 複迴歸表示式:
Y = β0 + β1X1 + β2X2 + … + βnXn + ε
β0 為常數,β1 … βn 為迴歸係數,ε 為誤差
==導入例題sample==
=>使用身高及腰圍去預測體重,解釋變數共有2個(身高跟腰圍)
| 身高 | 160 | 165 | 167 | 170 | 165 | 167 | 178 | 182 | 175 | 172 |
| ----- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 腰圍 | 67 | 68 | 70 | 65 | 80 | 85 | 78 | 79 | 95 | 89 |
| 體重 | 50 | 60 | 65 | 65 | 70 | 75 | 80 | 85 | 90 | 81 |
```python=
###多元回歸(複回歸)
#利用身高體重求出線性回歸,再預測
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
waist_heights = np.array([[67,160],[68,165],[70,167],[65,170],[80,165],
[85,167],[78,178],[79,182],[95,175],[89,172]])
#二維陣列(如果有三個變數因子,[67,160,**],資料結構仍為二維
weights = np.array([50,60,65,65,70,75,80,85,90,81])
X = pd.DataFrame(waist_heights, columns=["waist","heigh"])
y = pd.DataFrame(weights, columns=["weight"])
lm = LinearRegression()
lm.fit(X, y) #y代表要預估的值
#有幾個因數就會有幾個迴歸係數,但截距就只有一個
print("迴歸係數:",lm.coef_) #迴歸係數: [[0.71013574 1.07794276]]
print("截距:",lm.intercept_) #截距: [-166.36459731]
# 預測腰圍和身高[66,164],[82,172]的體重
new_waist_heights = pd.DataFrame(np.array([[66,164],[82,172]]))
predicted_weights = lm.predict(new_waist_heights)
print(predicted_weights) #[[57.28697457][77.2726885 ]]
```
**以下使用scikit-learn的資料集,Boston房價資料集,探討影響房價的因子**
以下連結為scikit-learn官方資料集介紹
https://scikit-learn.org/stable/datasets/toy_dataset.html
```python=
import pandas as pd
from sklearn import datasets
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
boston = datasets.load_boston()
print(boston.keys())
#dict_keys(['data', 'target', 'feature_names', 'DESCR', 'filename', 'data_module'])#
print(boston.data.shape)
#(506, 13) 幾列再幾欄
print(boston.feature_names)
#['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO' 'B' 'LSTAT']
X = pd.DataFrame(boston.data, columns=boston.feature_names)
target = pd.DataFrame(boston.target ,columns=["MEDV"])
#print(target.head())
y = target["MEDV"] # y資料格式變成是series
lm = LinearRegression()
lm.fit(X,y)#(X,y)=(dataframe,series)資料格式
print("迴歸係數:", lm.coef_)#迴歸係數共有13個
print("截距:", lm.intercept_)
coef = pd.DataFrame(boston.feature_names, columns=["features"])#從一維變二維(左到右的資料,變成上到下的資料)
coef["estimatedCoefficients"]=lm.coef_
#新增一個欄位為estimatedCoefficients,內容名稱為lm.coef_的數值,會把科學記號的數值乘回來,變成可以判斷大小的數值estimatedCoefficients
print(coef) #如下圖
"""變成dataframe
#RM數值最高,代表與房價最正相關
plt.scatter(X.RM, y)
plt.xlabel("Average number of rooms per dwelling(RM)")
plt.ylabel("Housing Price(MEDV)")
plt.title("Relationship between RM and Price")
plt.show()
"""
predicted_price = lm.predict(X)
print(predicted_price[0:5]) #[30.00384338 25.02556238 30.56759672 28.60703649 27.94352423]
#預估房價與真實房價作圖,圖示最右邊代表outliner(殘差)
plt.scatter(y ,predicted_price)
plt.xlabel("Price")
plt.ylabel("Predicted Price")
plt.title("Price vs Predicted Price")
plt.show()
```

