# 巨匠Python - 數統基礎 ###### tags: `資料分析` # 第一章、方程式操作 & 微分與極值 **前導:程式與數值計算關係** 1.統計分析 vs. 機器學習 統計:找出真相、因果推理 機器:解決問題、預測結果 2.數學:解決問題的方法 <線性> (1)如何解決問題-方程式 (2)固定&變動資訊-截距&斜率 (3)瞬間變化量-微分 (4)趨近值-極限 <非線性> (5)敘述統計:聚集、離散程度 (6)推論統計:資料無法探索 (7)機率、分配 (8)母體、抽樣、檢定、標準差 ------- **Google Colab** 1. 環境:Ubuntu + Python3.7 2. 套件:每次執行都得重新安裝 3. 檔案:執行完就會刪除 4. 免費版本不能於背景執行 ----- ## 一、線性方程式:求斜率&截距 [matplotlib.pyplot - Documentation](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.html) [numpy - Documentation](https://numpy.org/doc/stable/reference/generated/numpy.polyfit.htm) ----- **01. Set (in Google Colab)** ``` # !pip install matplotlib # !pip install numpy # ! 表示轉移至Linux環境下達指令 (離開python環境) import matplotlib.pyplot as plt import numpy as np x = [1,2,3,4,5,6,7] y = [1,3,3,12,5,7,9] plt.plot(x,y,'--') # x軸、y軸、虛線表示 plt.grid() # 增加格線 plt.show() # 顯示圖形 ``` ![](https://static.coderbridge.com/img/zxc61224/54650ca8975841479bbc6a92cdaf5aea.png) ----- **02. 轉換成線性方程式(斜率、截距)** ``` # 令有一次方程式: y = slope * x + intercept # np.polyfit(x,y,N): 可將現資料(x,y)調整找出N次方程式, 回傳list slope, intercept = np.polyfit(x,y,1) print(slope) print(intercept) # 若拆解成二次方程式 (y = a * x ** 2 + b * x + c) # 等號左邊可以得幾個值,視等號右邊會拆成幾個變數 a, b, c = np.polyfit(x,y,2) print(data) # 以一次方程式為例,列出每一個x值所對應y值(list) y1 = [slope * i + intercept for i in x] plt.plot(x,y,'--') plt.plot(x,y1,'r') #red plt.grid() plt.show() ``` ![](https://static.coderbridge.com/img/zxc61224/026f0ba3b223428d88182704cee22e20.png) ----- **練習一、經濟部1994-2004年經濟成長率** ``` x = np.arange(1994,2005,1) # 1994-2005,1年1格 y = [7.11,6.42,6.10,6.37,4.33,5.32,5.78,-2.22,3.94,3.33,5.71] # 以 polyfit 求一次方程式,以進行預測 slope, intercept = np.polyfit(x,y,1) print(f"斜率: {slope}") print(f"截距: {intercept}") # 產生list: 每一個x所對應的y值 y1 = [slope * i + intercept for i in x] plt.plot(x,y,'--') plt.plot(x,y1,'r') #red plt.grid() plt.show() # 試求二次方程式 (y = a * x ** 2 + b * x + c) a, b, c = np.polyfit(x,y,2) y1 = [a * i ** 2 + b * i + c for i in x] plt.plot(x,y,'--') plt.plot(x,y1,'r') #red plt.grid() plt.show() ``` ![](https://static.coderbridge.com/img/zxc61224/f3f1de4c347449f29be159c9c31bf097.png) ![](https://static.coderbridge.com/img/zxc61224/4b975d5146f8451eb08af80c14954d78.png) ----- **練習二、銷售業績計算(CSV)** * 若數值凌亂不一定可以推出線性方程式 => 以最近鄰概念進行推估 * 建議最高至三元(三欄位)即可,可以3D圖表呈現 * 連結google drive內檔案 ``` from google.colab import drive drive.mount('/content/drive', force_remount=True) # force_remount=True 強制安裝驅動器,避免中斷情形 ``` ``` import pandas as pd import numpy as np import matplotlib.pyplot as plt df = pd.read_csv("/content/drive/MyDrive/colab/Advertising.csv") x = df['Newspaper'] y = df['Sales'] plt.scatter(x,y) # 使用散佈圖 # plt.plot(x,y) # 使用曲線圖 plt.show() # 加入polyfit找出資料中的線性關係 a,b,c = np.polyfit(x,y,2) y1 = [a * i ** 2 + b * i + c for i in x] plt.scatter(x, y) plt.plot(x, y1, "r") plt.show() ``` ![](https://static.coderbridge.com/img/zxc61224/20dbcb21057644c68472b99a2af51921.png) **資料過於零散,無法得出有效表示關係之方程式** ----- ## 二、方程式求解 1. 需先以`物件 = sympy.Symbol('符號')`定義函式內物件 2. **f(x) = 0** 或 **聯立方程式** => 求變數解 * 以`sympy.solve([input],[output])` 求解(回傳dictionary) 3. **線性方程式 f(x) = ax+by+c** => 求每一變數對應值 * 以`sympy.lambdify((x, y), function)`或`sympy.Lambda((x, y), funciton)`建立物件計算 4. **二次函數**極值與圖形 * 以`numpy.arange`限定範圍求`var.argmin()`或`var.argmax()` * 以`matplotlib.pyplot.scatter(x,y)`散佈圖點出極值位置 * 亦可微分(`.diff`)求解(`.solve`)並帶回原式(`.lambdify`) ----- ### (一) 二元一次聯立方程式 ``` # eg 1. import sympy as sp import numpy as np x = sp.Symbol('x') y = sp.Symbol('y') f1 = 2 * x + 3 * y - 23 f2 = x + 4 * y - 24 print(sp.solve([f1, f2], [x, y])) > {x: 4, y: 5} ``` ``` # eg 2. # 有草莓(50元)、巧克力(30元)兩種冰淇淋 s = sp.Symbol('s') c = sp.Symbol('c') # 總數量 = 20個 f1 = s + c - 20 # 總金額 = 800元 f2 = 50 * s + 30 * c - 800 # f1, f2 表示兩個答案為零的方程式 answer = sp.solve([f1, f2], [s, c]) print(answer) print(answer.__class__) # 回傳資料的屬性 print(type(answer)) # 回傳資料的型態 print("草莓冰淇淋份數: ", answer[s]) print("巧克力冰淇淋份數: ", answer[c]) > {s: 10, c: 10} > <class 'dict'> > <class 'dict'> > 草莓冰淇淋份數: 10 > 巧克力冰淇淋份數: 10 ``` ----- ### (二) 線性方程式求解 lambdify vs. Lambda ``` from sympy import lambdify, Symbol, Lambda import numpy as np ''' lambdify vs. Lambda ddx = lambdify(自變數, 方程式) answer = ddx(自變數代入數值) func = Lambda(自變數, 方程式) answer = func(自變數代入數值) ''' print("\n\n----- 若x = -1,求一階導數的結果 -----") x = sp.Symbol('x') y1 = 2 * np.power(x,4) - 3 * np.power(x,2) + 2 * x - 20 print("\n原方程式: ", y1) y2 = y1.diff(x) print("一階函式: ", y2) y3 = 8 * (-1) ** 3 - 6 * (-1) + 2 print("\n【法1】直接代入: ",y3) ddx = lambdify(x, y2) print("\n【法2】使用lambdify: ",ddx(-1)) func = sp.Lambda(x, y2) print("\n【法3】使用Lambda: ",func(-1)) print("\n\n----- 使 x = -5 ~ 5,判斷函式圖形 -----") ddx = lambdify(x, y1) print("\n【法1】使用lambdify:", ddx(np.arange(-5, 5, 1))) func = Lambda(x, y1) # print(func(np.arange(-5, 5, 1))) => error print("\n【法2】使用Lambda: errer - 無法代入list") print("\n\n----- 若x = 3, y = 7,二元方程式求解 -----") x = sp.Symbol('x') y = sp.Symbol('y') f = x ** 2 - 2 * y + 4 * x -3 print("\n令二元方程式: ", f) ddx = lambdify((x, y), f) print("\n【法1】使用lambdify: ", ddx(3, 7)) func = Lambda((x, y), f) print("\n【法2】使用Lambda: ", func(3, 7)) print("\n**lambdify物件: ", ddx.__class__) print("**Lambda物件: ", func.__class__) ``` ![](https://static.coderbridge.com/img/zxc61224/bdc0f979a7e74cc2a476a6b744ce87cf.png) ----- ## 三、微分與極限求解 1. 一次函數 `f'(x) = f.diff(x)` 2. 極限函式 `sympy.limit(函式, 自變數,趨近值)` 3. 以 `sp.oo` 表示無限大 ``` # ---------- 微分 ---------- # # 意義:求瞬間變化量 x = sp.Symbol('x') y = np.power(x,5)+ 2*np.power(x,4)+ 3*np.power(x,3)+ 4*np.power(x,2)+ 5*x+ 6 y2 = y.diff(x) # 對y做x的微分 print(y2) > 5*x**4 + 8*x**3 + 9*x**2 + 8*x + 5 # ---------- 極限 ---------- # # 意義:求 x = ? 會使 函式 趨近於 趨近值 x = sp.Symbol('x') f3 = sp.limit((x**2+2*x-3)/(x-1),x,sp.oo) print(f3) > oo ``` # 第二章、二次函數與矩陣 ## 一、二次函數-極值與圖形 ``` import sympy as sp print("\n---- 令x為正負10以內整數,求極值 ----") x = np.arange(-10, 11, 1) y = -3 * x ** 2 + 20 * x + 3 y_max = np.max(y) x_max = x[y.argmax()] print("\n求圖形最高點: ", x_max, ",", y_max) print("\n---- 繪製二次函數圖形 (放大、並標示最大值) ----") # 放大圖表 plt.figure(figsize=(8, 5)) plt.plot(x, y) # 以散佈圖方式點出最大值 plt.scatter(x_max, y_max, c='r') plt.grid() plt.show() print("\n---- 以微分求極值 ----") x = sp.Symbol("x") y = -3 * x ** 2 + 20 * x + 3 y_diff = y.diff(x) x_max = sp.solve([y_diff],[x])[x] ddf = sp.lambdify(x, y) y_max = ddf(x_max) print("\n求圖形最高點: ", x_max, ",", y_max) ``` ![](https://static.coderbridge.com/img/zxc61224/0ce2cd4d26494738b98ae88fa46cc207.png) ## 二、矩陣與運算 ### (一) 矩陣運算 ``` # 2x2 矩陣運算 import numpy as np a = np.array( [ [6,3], [8,10] ]) b = np.array( [ [1,2], [0,1] ]) print("a") print(a) print("b") print(b) print("-"*20) print("a*b => 點對點相乘") print(a*b) print("-"*20) print("np.dot(a,b) => 二維矩陣內積相乘(row對應column)/前方矩陣轉置") print(np.dot(a,b)) print("-"*20) print("np.inner(a,b) => 一維矩陣方式相乘(row對應row)/後方矩陣轉置") print(np.inner(a,b)) print("-"*20) print("np.outer(a,b) => 二維矩陣外積相乘") print(np.outer(a,b)) ``` ![](https://i.imgur.com/FzoR4rg.png) --- **練習一、矩陣應用** ``` gamer = np.array([ [15, 14, 15], # A校排球、游泳、田徑隊人數 [12, 13, 17] # B校排球、游泳、田徑隊人數 ]) # 2x3 矩陣 cost = np.array([ [10, 14], # 排球隊訓練 & 場地成本 [5, 18], # 游泳隊訓練 & 場地成本 [8, 10] # 田徑隊訓練 & 場地成本 ]) # 3x2 矩陣 total_cost = gamer.dot(cost) print(total_cost) print(total_cost.sum(axis=1)) ''' [[340 612] [321 572]] [952 893] ''' ``` **練習二、3x3矩陣內積計算** ``` import numpy as np a=[ [50,40,15], [20,32,47] ] b=[ [10,14], [5,8], [8,10] ] print(np.dot(a,b)) ''' [[ 820 1170] [ 736 1006]] ''' ``` ### (二) 特殊矩陣 1. 單位矩陣: `np.eye(3)` 2. 轉置矩陣: `square.T` 3. 反矩陣: `np.linalg.inv(square)` * row & column數量要相同才可算出反矩陣 * 矩陣與單位矩陣內積相乘 = 單位矩陣 * 並非每個矩陣有反矩陣 => 不可逆矩陣 --- # 第三章、敘述統計 ## 一、統計學分類與介紹 **敘述統計 & 推論統計** 1. 敘述統計 * 資料整理 * 圖表 * 變異數 * 標準差 * 離散程度 2. 推論統計 * 機率分配 * 檢定方式 * 多變量分析 * 獨立性檢定 * 迴歸分析 **統計資料型態** 1. 以資料發生時間區分 => 橫斷面資料 & 時間序列資料 2. 以資料屬性區分 => * 質性 * 名目Nominal: ex. 1是男生, 2是女生 * 順序Ordinal: ex. 1-5 代表喜歡的程度 * 量化 * 離散Discrete: ex. 學生的成績 * 連續Continuous: ex. 學生的身高 & 體重 **範例一、名目資料統計** ``` import collections as ct lang=['Python','Java','C#','C++','python','VB','Python'] count = ct.Counter(lang) # 各筆名目資料的數量 print(count) # 特定資料的數量 print(count['Python']) ''' > Counter({'Python': 2, 'Java': 1, 'C#': 1, 'C++': 1, 'python': 1, 'VB': 1}) > 2 ''' ``` --- ## 二、敘述統計-數據分析 **使用工具安裝** ``` import numpy as np import stats as sts import matplotlib.pyplot ``` **常見統計指標與函式** 1. 平均數計算: `np.meam()` * 圖形標示: `plt.axvline(np.mean(datas),0,1,c='r')` 2. 中位數計算: `np.median()` * 圖形標示: `plt.axvline(np.median(datas),0,1,linestyle='--')` 3. 全距計算: `np.ptp()` 4. 四分位數: eg. Q1 `np.percentile(datas, 25)` * 圖形標示: `plt.axvline(np.percentile(money, 25),0,1,c='g')` 5. 四分位距 = Q3-Q1: `np.percentile(datas, 75)-np.percentile(datas, 25)` 6. 變異數 = 平均差值平方: `np.var()` 7. 標準差 = 標準差開根號: `np.std()` 8. 變異係數 = 平均數/標準差: `np.mean() / np.std()` * 用途: 不同單位、不同標準差資料之比較 9. 標準分數 = (數值-平均值)/標準差 `(value-mean)/std` * 用途: 相同單位、不同標準差資料之比較 10. 共變異數 = `np.cov(b,a)` * 用途: 求得兩數字的相對波動程度(和共變異數作比較) * 矩陣左上值: b值相對變異數 * 矩陣右下值: a值相對變異數 * 矩陣反向對角線: 共變異數 11. 相關係數 = `np.corrcoef(a,b)` * 用途: 求得兩數字互相影響的程度(介於-1到1之間) * -1~0 => 負相關 * 0 => 無相關 * 0~1 => 正相關 * 絕對值 > 0.75 => 強烈正/負相關 12. 偏態係數 = `sts.skewness(data)` * 用途: 了解圖形的對稱程度 * SK=0,圖形對稱 * SK>0,右偏、正偏,少數資料大,平均值>中位數 * SK<0,左偏、負偏,少數資料小,平均值<中位數 13. 峰度係數 = `sts.kurtosis(data)+3` * 用途: 了解圖形的陡峭程度(統計上以3為基準,和3做比較) * 修正: 因程式以0為基準,故須+3 * Kurtosis=3,常態峰,與常態分配圖形相同 * Kurtosis>3,高峻峰,較常態分配陡峭 * Kurtosis<3,低闊峰,較常態分配平緩 :::info :label: **變異係數與標準分數判斷法** 變異數越低 => 可靠性越高 => 標準差越低 => 算出變異係數越高 (mean/std) => 算出標準分數越高 ((score-mean)/std) => 表現越好 ::: --- ## 三、敘述統計-圖表繪製 **使用工具安裝** ``` import matplotlib.pyplot ``` **圖表適用性與函式** 1. 折線圖Plot: 適用連續型函數 * `plt.plot(x, y)` 2. 長條圖Bar: 適用離散型函數 * `plt.bar(x, y)` 3. 散佈圖Scatter: 了解x軸與y軸屬性關係 * `plt.scatter(x,y)` 4. 直方圖Hist: 了解資料分組後數量 * `plt.hist(datas, bins=%組別數量%)` 5. 圓餅圖Pie: 了解資料於百分比內比例 6. 箱型圖Box: 了解資料分布的離散程度 * `plt.boxplot(datas)` --- ## 四、實作練習 **練習一、學生成績分析** ``` # ----- 數據分析 ----- # np1=np.array([15,10,30,30,30,25,25,55,57,54,80,75,77,84,91,92,88,90,95,86]) # 要是numpy物件型態才可使用函式 print("中位數:",np.median(np1)) print("平均值:",np.mean(np1)) print("筆數:",len(np1)) # ----- 圖表繪製 ----- # import matplotlib.pyplot as plt ## 設定橫軸: 總筆數 x = np.arange(0,len(np1)) # 依照實際數據呈現 plt.bar(x,np1) # 長條圖 # plt.plot(x,np1,c="r") # 曲線圖 plt.show() ``` ![](https://i.imgur.com/fGmXM8I.png) ![](https://i.imgur.com/71497dk.png) --- **練習二、2017勞動部公布各行業初到職薪資** ``` # ----- 數據分析 ----- # money=np.array([27583,27555,26492,29441,24973,27499, 26421,29686,27156,26771,25499,26571,28029,27624, 30176,31058,29404,27492,27092,26941,27507,27519, 26029,28207,28825,27307,27502,26676,26621,24789, 26759,29928,29517,32492,28628,28467,32777,26276, 25981,28537,26853,27702,29885,29653,27005,26066, 27628,26758,27682,25679,28294,31711,27439,25416, 26491,32800,33325,35821,28181,27548,38151,27932, 26304,25269,27024,26765,28832,27956,25540,26941, 28626,29984,29440,32044,36354,25470,28820,32522, 30741,29201,36384,29176,28092,29266,27383,29052,32467, 28191,28852,29854,28025,28838,26941,26243,28168,25263, 25426,25607,26804,26062,26374,26392,27739,26006, 27635,25896,24614,24701,23187,25841]) print(f"總筆數: {len(money)}") print(f"平均數: {np.round_(np.mean(money), decimals=2)}") print(f"中位數: {np.median(money)}") print(f"最高薪: {np.max(money)}") print(f"最低薪: {np.min(money)}") print(f"全距: {np.ptp(money)}") print(f"25%位置上的薪資{np.percentile(money, 25)}") print(f"75%位置上的薪資{np.percentile(money, 75)}") print(f"變異數: {np.var(money)}") print(f"標準差: {np.std(money)} (變異數開根號)") print('偏態係數:',sts.skewness(money)) print('峰度係數:',sts.kurtosis(money)+3) print("-"*20) # ----- 圖表繪製 ----- # import matplotlib.pyplot as plt plt.hist(money, bins=5) # 第25%, 50%, 75%筆資料位置 plt.axvline(np.percentile(money, 25),0,1,c='g') plt.axvline(np.mean(money),0,1,c='y') plt.axvline(np.percentile(money, 75),0,1,c='r') # 平均數位置 plt.axvline(np.median(money),0,1,linestyle='--',c='purple') plt.show() # 箱型圖: 可知離散程度 plt.boxplot(money) plt.show() ``` ![](https://i.imgur.com/1gy99bM.png) ![](https://i.imgur.com/qooQ49o.png) --- **練習三、數學最高分及國文最高分-程度比較** ``` import numpy as np math = np.array([40,25,80,50,44,64,90,85,60,65]) chinese = np.array([61,71,55,70,78,68,60,66,90,80]) math.sort() # 預設由小到大 chinese.sort() print("math_mean =",math.mean()) print("chinese_mean =",chinese.mean()) print("math_std =", round(math.std(),2)) print("chinese_std =", round(chinese.std(),2)) print("\n","-"*10,"\n") print("(一) 單位不同時:可以變異係數作比較,數值高表示離散程度高,誤差值大\n") print("數學變異係數 =",round(math.mean()/math.std(),2)) print("國文變異係數 =",round(chinese.mean()/chinese.std(),2)) print("\n","-"*10,"\n") print("(二) 單位相同時:可以先轉成標準化值(z-score)再作比較\n") math_standardized=[] chinese_standardized=[] for score in math: score = round((score - math.mean())/ math.std(),2) math_standardized.append(score) for score in chinese: score = round((score - chinese.mean()) / chinese.std(),2) chinese_standardized.append(score) print(math_standardized) print(chinese_standardized) ``` ![](https://i.imgur.com/EGaEayE.png) --- **練習四、共變異數與相關係數** ``` a=np.array([5.4,-4.2,10.4,11.2,-7.8,-2]) b=np.array([3.4,-1.2,7.5,5.2,3,-5]) print('共變異數的推算,計算波動的程度') print(np.cov(b,a)) # 左上: 前者(b)相對變異數 # 右下: 後者(a)相對變異數 # 反對角線: 共變異數 # 可得結果: b很穩定, a變動性大 print('\n相關係數的推算,計算兩者的相關性') print(np.corrcoef(a,b)) ``` ![](https://i.imgur.com/14jXMsE.png) --- # 第四章、機率分配 :::success * 間斷型資料中的二項分配、超幾何分配、Poisson分配。 * 當資料量龐大(例如十萬筆),資料分配就會落於平均值附近。 * 連續型資料中常態分配,資料分配具有落於平均值附近的特性。 * 基於上述的資料分配我們就可以知道,各種資料的分布: 1.平均值=中位數 (資料量必須夠大) 2.在正負一個標準差範圍內的資料數約佔68%比例。 3.在正負兩個標準差範圍內的資料數約佔95%比例。 4.在正負三個標準差範圍內的資料數約佔99%比例。 * 上述四點也是中央極限定理、假設檢定、Z檢定、T檢定等的基本原理。 ::: ## 一、基本機率分配概念 ![](https://i.imgur.com/CFhhJX0.png) **00. 隨機變數** *=> 試驗結果* 1. 離散型變數 => 結果有限 ex.丟硬幣結果(正/反)、整數的結果 主要計算:平均值、變異數、期望值 2. 連續型變數 => 結果無限 ex.銷售金額(無限大)、身高(無窮小數) 主要計算:機率密度函數 **01. 機率分配** *=> 資料於統計中的分布,包括對位置、散佈、形狀的描述* [特定分布的資料] + [機率分配] = [找出資料分布的機率與形狀] 1. 主要描述:離散型變數 (1) 二項分配 => 結果只有兩種 (2) 超幾何分配 (3) 波瓦松分配 2. 主要描述:連續型變數 (1) 均勻分配/矩形機率分配 (2) 常態分配 **random函式操作** 1. 隨機生成 整數 * 不包含結束值: ==`numpy.random.randint()`== * ra1.randint(4,5,(2,2)) * 包含結束值: `random.randint()` * ra2.randint(4,5) 2. 隨機生成 0~1 小數 * 最多只能產生一個數值: `random.random()` * ra2.random() * 最多只能產生一維矩陣: ==`numpy.random.random()`== * ra1.random(5) * 可以產生多維矩陣: ==`numpy.random.rand()`== * ra1.rand(2,2,2)*10 3. 隨機生成 1~10 小數 * 最多只能產生一個數值: `random.random()` * ra2.random() * 9 + 1 * 最多只能產生一維矩陣: ==`numpy.random.random()`== * ra1.random(5) * 9 + 1 * 可以產生多維矩陣: ==`numpy.random.rand()`== * ra1.rand(2,2) * 9 + 1 4. 針對list的隨機套件 * 在list中隨機挑選一個值: `random.choice()` * ra2.choice(list) * 將list內資料順序打亂: `random.shuffle()` * ra2.shuffle(list) * 從list中隨機獲取5個元素返回: `random.sample()` * ra2.sample(list, 5) * 從list中隨機挑選多個值: ==`numpy.random.choice()`== * args1: `list` * args2: `取出的數目` * kwargs: `p=[0.3, 0.3, 0.2, 0.1, 0.1]` (被抽出機率) * kwargs: `replace=False` (重複值的可能) 5. 兩矩陣是否相同 * 不可直接用 if `a == b` * if `(a==b).all()`: 兩矩陣是否完全相同 * if `(a==b).any()`: 兩矩陣是否有位置相同的數值 **案例一、尾牙抽獎** ``` # 設定不同獎金中獎機率 # 設定每桌獎項不重複 money = [100,200,500,1000,5000,10000] for table in range(5): np1 = ra1.choice( money, # 選擇的list 3, # 抽出的數目 p=[0.3,0.3,0.2,0.1,0.1,0], # 各項目被抽出機率 replace=False) # 重複值的可能 print(np1, end=" ") ``` --- ## 二、離散型變數機率分配 ### (一) 二項分配 * 結果只有 0 與 1 * 各項結果互相獨立 * 公式: `numpy.random.binomial(n,p,size)` * n: 操作次數(ex.每輪丟100次硬幣) * p: 成功機率(介於0與1之間) * size: 實驗數量(ex.實驗100輪) **案例一、骰硬幣** ``` import numpy as np import matplotlib.pyplot as plt ps = [] for _ in range(0,1000): # 得20局,每局丟100次硬幣,各局正面朝上的次數 a = np.random.binomial(100, 0.5, 20) # 平均每局正面朝上的次數 ps.append(np.mean(a)) # 得1000輪後的平均次數,操作次數越多,結果越接近估計值 print(np.mean(ps)) plt.hist(ps) plt.show() ``` ![](https://i.imgur.com/kplG8HQ.png) **案例二、消費者喜好調查,恰兩人喜歡的機率** ``` import numpy as np import matplotlib.pyplot as plt round = 10000 # 總共訪問輪數 times = 10 # 每輪訪問次數 customers = 4 # 每次訪問人數 percent = 0.25 # 每人喜歡的機率 total = round * times count = 0 list = [] for i in range(round): a = sum( # 得訪問10次,每次訪問4人中,表示喜歡的人數 np.random.binomial(customers, percent, times) ==2) # 等於2的次數 => 進行加總 list.append(a/10) count += a print(count / total) plt.hist(list) plt.axvline(count / total,0,1,c="red") plt.show() ``` ![](https://i.imgur.com/QF87jl7.png) --- ### (二) 超幾何分配 * 結果只有 0 與 1 * 各項結果"不"互相獨立 * 公式: `numpy.random.hypergeometric(ngood, nbad, nsample, size=None)` * ngood:目標資料總數 * nbad:非目標資料總數 * nsample:每次抽出數量 * size: 試驗次數 * 需要前三筆資料:因為連續抽取情況下,會影響抽取結果 * 若(樣本/母體 < 0.05),可使用二項分配取代(影響不大) :::info :spiral_note_pad: **二項分配 vs. 超幾何分配** **二項分配:每次結果獨立** 連續抽取多人: (1) 抽幾次? (2) 抽中機率多少? => 抽完會放回,故母體不減少、機率不改變 **超幾何分配:每次結果非獨立** 連續抽取多人: (1) 兩群各有多少人? (2) 抽幾次? => 抽完不放回,故母體會減少,機率會改變 ::: **案例三、班上同學5男15女,求抽查到男生作業的機率** ``` import numpy.random as nr import matplotlib.pyplot as plt # 二項分配 a = nr.binomial( 3, # 總共抽3人 0.25, # 抽到男生的的機率 ## 二項分配只要機率就好 20 # 抽20次 ) print(a) # 超幾何分配 s = nr.hypergeometric( 5, # 男生群5人 ## 超幾何分配需要兩群體大小 15, # 女生群15人 ## 超幾何分配需要兩群體大小 3, # 總共抽3人 20 # 抽20次 ) # 得到回傳值: 20次中,抽到目標的次數 print(s) ``` --- ### (三) Poisson分配 (卜瓦松分配) * 相同的時間區間內(ex.一年內) * 不連續發生的事件 * 各項結果互相獨立 * 公式: `numpy.random.poisson(lam,size)` * lam: 事件發生次數 * size: 試驗次數 * 適合描述單位時間內隨機事件發生次數的機率分布 * 若不符合"獨立"或"隨機",則使用常態分配 * 實務上使用機會少 **案例四、去年發生3次地震,今年發生少於3次的機率** ``` import numpy as np import numpy.random as nr x=nr.poisson(lam=3,size=100) print(np.mean(x<3)) ``` --- ## 三、連續型變數機率分配 ### (一) 均勻分配 * 連續型分布 * 公式: `numpy.random.uniform(low, high, size)` * ex. 高雄捷運發車時間 ``` import numpy as np import matplotlib.pyplot as plt s = np.random.uniform(5,10,1000) plt.hist(s,15) plt.show() ``` ![](https://i.imgur.com/jorpset.png) --- ### (二) 常態分配 * 連續型分布 * 公式: `numpy.random.normal(loc, scale, size)` * loc: 平均值 * scale: 標準差 * ex. 班上女同學的身高 ``` import numpy.random as nr import matplotlib.pyplot as plt x=nr.normal(loc=5, scale=1, size=100) y=nr.normal(loc=5, scale=2, size=100) z=nr.normal(loc=5, scale=3, size=100) plt.hist(z,color='b') plt.hist(y,color='g') plt.hist(x,color='r') plt.show() ``` ![](https://i.imgur.com/KcdvcFb.png) --- # 第五章、推論統計-抽樣估計 [樣本變異數 & 自由度補充資料](https://blog.udn.com/nilnimest/92412101) ## 一、推論統計基本概念 * 估計(Estimation):從樣本資料推論母體特徵(平均數與標準差) * 假設檢定(Hypothesis Testing):先針對母體提出假設,再從樣本驗證其是否有效 * 虛無假設 * 對立假設 * 信賴區間 ## 二、母體與抽樣 1. 抽樣與普查 * 考量: 必要性、可行性、偽陰或偽陽的可能 2. 準確度與精確度 * 準確度: 與實際資料接近的程度 * 精確度: 抽查樣本相似的程度 3. 抽樣的四個方法 * 簡單隨機抽樣(simple random sampling) * 又稱純隨機抽樣 * 每個樣本抽取機率均等 * 優點: 容易執行 * 缺點: 需有母體清單、易產生較大誤差 ![](https://i.imgur.com/jILcdW0.png) * 系統抽樣(systematic sampling) * 又稱等距抽樣 * 先隨機抽取地初始樣本,再等距離抽取其他樣本 ![](https://i.imgur.com/4JCk5Rl.png) * 分層抽樣(stratified sampling) * 將母體按某種特徵或規則劃分不同的層,再從不同層中獨立抽樣 * 優點: 控制樣本規模,誤差小 * 缺點: 成本高 * 適用於層與層間差異性大,而層內個體差異性小 ![](https://i.imgur.com/y1j8mJT.png) * 整群抽樣(cluster sampling) * 將母體中若干個單位合併為組,抽樣時直接抽取群,再抽樣 * 優點: 成本低,沒有母體清冊亦可執行 * 缺點: 小群組同性質高時,易造成資料辨識度差 * 適用於群體與群體差異性小;而群體內個體差異性大 ## 三、樣本與估計 1. 點估計與區間估計 * 點估計(Point Estimation):估計出單一值 * ex. 男性平均身高170公分 * 區間估計(Interval Estimation):估計出範圍值,又可稱==信賴區間== * ex. 男性平均身高是161~179公分 2. 抽樣誤差與非抽樣誤差 * 抽樣誤差: 來自樣本與母體的差異 * 可藉由增加樣本數修正 * 非抽樣誤差: 來自於實驗方法的錯誤 * 需透過妥善規劃與嚴格審查修正 ## 四、母體與樣本的計算 :::info **結論:** 1. 母體特性: * 母數越多,越接近常態分配 3. 樣本特性 * 大數法則:樣本數越多,樣本平均越接近母體平均 * 中央極限定理:樣本數越多,樣本平均數的分配越接近常態分配 * 無論母體是否為常態分配 ::: ``` # ----- 產生母體 ------ # dice=[1,2,3,4,5,6] population=[] # 為產生連續性資料 for x in range(10000): sample=np.random.choice(dice,100) population.append(sample.mean()) print('母體平均數: ',np.mean(population)) print('母體標準差: ',np.std(population)) print('母體資料總數: ',len(population)) # 依母體平均與標準差 => 常態分佈圖 mu=np.mean(population) sigma=np.std(population) x=np.random.normal(mu,sigma,10000) plt.hist(x,color='red',label='normal distribution') # 真實的母體資料 plt.hist(population,color='blue',label='population') plt.legend(fontsize=10) plt.show() ``` ![](https://i.imgur.com/U2HWPGD.png) ``` # ----- 抽樣 ------ # mean_diff=[] #平均數差異值 mean_list=[] #儲存樣本的平均數 std_list=[] #儲存樣本的標準差 samples=[] #儲存樣本資料 samples_sizes = [10,100,1000,5000] for sample_size in samples_sizes: # 在母體中抽取sample size的樣本 sample = np.random.choice(a=population,size=sample_size) samples.append(sample) print('抽樣的樣本數:',sample_size) print('樣本的平均數:',np.mean(sample)) print('樣本的標準差:',np.std(sample)) mean_different = np.mean(sample) - np.mean(population) mean_diff.append(mean_different) mean_list.append(np.mean(sample)) std_list.append(np.std(sample)) print('-'*70) print(mean_diff) b=np.array(mean_diff) print(f"母體平均與樣本平均-差異值最小大約是: {np.min(np.abs(mean_diff)): .5f}") plt.hist(population,color='blue') #隨機產生的母體資料 plt.hist(sample,color='green') #最後一個sample的資料最接近母體 plt.show() ``` ![](https://i.imgur.com/RUpBEfA.png) ``` # 以散佈圖了解抽樣數目不同時,樣本間的關係 plt.scatter(np.mean(population),np.std(population),c='red',label='population') plt.scatter(mean_list[0],std_list[0],c='black',label='10sample') plt.scatter(mean_list[1],std_list[1],c='green',label='100sample') plt.scatter(mean_list[2],std_list[2],c='blue',label='1000sample') plt.scatter(mean_list[3],std_list[3],c='yellow',label='5000sample') plt.legend() plt.xlabel('mean') plt.ylabel('std') plt.show() # 故樣本數越大,越接近母體真實資料 ``` ![](https://i.imgur.com/ltDKbF8.png) ``` # 以直方圖了解抽樣數目不同時,樣本間的關係 fig,ax=plt.subplots(4) ax[0].hist(samples[0]) ax[1].hist(samples[1]) ax[2].hist(samples[2]) ax[3].hist(samples[3]) plt.show() # 故樣本數越大,樣本分布越接近常態分配 ``` ![](https://i.imgur.com/35UBXaS.png) --- # 第六章、推論統計-信賴區間與假設檢定 ![](https://i.imgur.com/2EWJWhp.png) ## 一、基本名詞解釋 1. 預期正確的機率 * 信賴係數(confidence level) * 信賴水準(confidence coefficient) 2. 預期錯誤的機率 * 顯著水準(significant level) * α(alpha) 3. 此預期的區間 * 信賴區間(confidence interval) 4. 此預期的邊界 * 信賴界限(confidence limit) 5. 利用z-score標準化分數 * z-score 6. 轉換語法 ``` import scipy.stats as st # 信賴水準 => z分數 st.norm.ppf(.95) # z分數 => 信賴水準 st.norm.cdf(1.64) ``` ## 二、假設檢定流程 ### (一)提出虛無假設和對立假設 #### 虛無假設和對立假設 1. 設定希望推翻的目標為虛無假設(H0) * ex. 一般情形、無罪、可信任客戶 2. 期望證實的結果為對立假設(H1) * ex. 想證明的特殊觀點、有罪、不可信任 * 要有足夠證據才能證錯 3. 依據H0訂定範圍,將檢定形式分為單尾或雙尾檢定 #### 型 I 錯誤 & 型 II 錯誤 實際是H0(positive),正確接受 => TP 實際是H1(negative),正確推翻 => TN 實際是H0(positive),錯誤推翻 => FP => 型I錯誤 實際是H1(negative),錯誤接受 => TN => 型II錯誤 :::success **型一錯誤:False Positive 錯誤拒絕(棄真錯誤、α錯誤、偽陽性)** 1. 實際是有信用的,錯誤拒絕 (後果嚴重,盡量避免) 2. 影響信賴區間,可透過增加樣本數修正 **型二錯誤:False Negative 錯誤接受(存偽錯誤、β錯誤、偽陰性)** 1. 實際是無信用的,錯誤接受 2. 偏向外部或其他因素造成 ::: ### (二)選擇檢定統計量 (test statistic) 1. 母體已知:無論樣本數大小,皆使用 z 分配 (常態分配) 2. 母體未知: * 當樣本數 n > 30,可以使用 z 分配 (常態分配) * 當樣本數 n < 30,使用 t 分配 ### (三)決定決策法則 (臨界值 or P-value) #### 1. 臨界值法 (Critical value method) 使用臨界值法時,我們一般會給定拒絕域 (拒絕H0的區域)以及接受域 (不拒絕H0的區域),當檢定統計量落入拒絕域時,則表示我們的樣本有足夠的證據來拒絕H0;反之,當檢定統計量落入接受域的時候,就表示我們的樣本資訊沒有足夠的證據來拒絕H0。 #### 2.P值法 (P-value method) 1. p-value是在假設虛無假設為真的前提下,觀察到檢定統計量比取樣得到的值更極端的機率 2. p-value越小,表示檢定的結果越顯著,越可以拒絕假設檢定中的虛無假設。 3. 若P值小於 α ,則拒絕虛無假設 (H0),否則便無法拒絕H0。 ### (四)比較結果,產生結論 ## 三、混淆矩陣(Confusion Matrix) ![](https://i.imgur.com/p76h0Sb.png) ### 準確率(Accuracy)= (tp+tn)/(tp+fp+fn+tn) 正確判斷有信用或無信用客戶的機率 ### 精確率(Precision)= tp/(tp+fp) **<假設positive,正確的機率> 1. 以預測為主 2. 預測有信用,正確預測的機率 ### 召回率(Recall)= tp/(tp+fn) **<真實為positive,正確的機率> 1. 以實際為主 2. 有信用的客戶,正確預測的機率