章節一、方程式操作 & 微分與極值


Posted by pei_______ on 2022-06-22

前導:程式與數值計算關係

1.統計分析 vs. 機器學習
統計:找出真相、因果推理
機器:解決問題、預測結果

2.數學:解決問題的方法

<線性>
(1)如何解決問題-方程式
(2)固定&變動資訊-截距&斜率
(3)瞬間變化量-微分
(4)趨近值-極限

<非線性>
(5)敘述統計:聚集、離散程度
(6)推論統計:資料無法探索
(7)機率、分配
(8)母體、抽樣、檢定、標準差


Google Colab

  1. 環境:Ubuntu + Python3.7
  2. 套件:每次執行都得重新安裝
  3. 檔案:執行完就會刪除
  4. 免費版本不能於背景執行

一、線性方程式:求斜率&截距

matplotlib.pyplot - Documentation

numpy - Documentation


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() # 顯示圖形


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()


練習一、經濟部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()



練習二、銷售業績計算(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()


資料過於零散,無法得出有效表示關係之方程式


二、解方程式

  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__)


二次函數-極值與圖形

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)


三、微分與極值

  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









Related Posts

C# 自訂Json檔

C# 自訂Json檔

Command Line 基本指令

Command Line 基本指令

![MTR04] W2 D6 函式、參數與引數

![MTR04] W2 D6 函式、參數與引數


Comments