引言
在前序對機器學習的探究過程中,我們已經深刻體會到人工智能到處都有微分求導運算,相關文章鏈接包括且不限于:
BP神經網絡
邏輯回歸
對于pytorch張量,求導運算必不可少,所以本次就專門來學習一下。
f-string的用法
f-string是python語言里面一種簡潔且強大的字符串格式化方法,對內容的引用和輸出較為高效。
確實也可以不適用f-string,但剛好學習到導數計算比較簡單,所以就一起學習一下。
f-string以“f”或“F”開頭,用單引號“‘”和“’”引用自由添加的字符串,如果要引用變量,就用大括號“{}”包起來。
常規輸出
常規輸出格式:f+‘輸出內容+{“引用內容”}’。示例代碼:
h = 0.1234567
print(f'h當前值:{h}')
?
這個代碼的運行效果:h當前值:0.1234567
控制小數位數輸出
常規輸出格式:f+‘輸出內容+{“引用內容:.xf”}’。
“引用內容:.xf”的意思是,對浮點數f,保留x位小數。示例代碼:
h = 0.1234567
print(f'h當前值:{h}')
print(f'h當前值(1位小數):{h:.1f}')
print(f'h當前值(3位小數):{h:.3f}')
print(f'h當前值(5位小數):{h:.5f}')
print(f'h當前值(8位小數):{h:.8f}')
print(f'h當前值(10位小數):{h:.10f}')
由圖2可見,h的當前值按照x的設置量調整了小數位數。
如果想把代碼寫得緊湊,比如寫成一個for循環,上述代碼可優化為:
h = 0.1234567
print(f'h當前值:{h}')
print(f'h當前值(1位小數):{h:.1f}')
print(f'h當前值(3位小數):{h:.3f}')
print(f'h當前值(5位小數):{h:.5f}')
print(f'h當前值(8位小數):{h:.8f}')
print(f'h當前值(10位小數):{h:.10f}')
for i in range(10):print(f'h當前值保留{i}位小數:{h:.{i}f}')
需要注意的是,引用的變量應該用大括號"{}"包起來。
代碼運行效果為:
pytorch導數
計算導數的定義式為:
f ′ ( x ) = lim ? x → 0 f ( x + h ) ? f ( x ) h f^{'}(x)=\lim_{x \to 0}\frac{f(x+h)-f(x)}{h} f′(x)=x→0lim?hf(x+h)?f(x)?
基于此,繼續優化代碼:
h = 0.1234567
print(f'h當前值:{h}')
print(f'h當前值(1位小數):{h:.1f}')
print(f'h當前值(3位小數):{h:.3f}')
print(f'h當前值(5位小數):{h:.5f}')
print(f'h當前值(8位小數):{h:.8f}')
print(f'h當前值(10位小數):{h:.10f}')
for i in range(5):print(f'h當前值保留{i}位小數:{h:.{i}f}')# 定義原函數
def f(x):return 3*x**2-3*x# 定義求導函數
def numerical_lim(f, x, h):return (f(x + h) - f(x)) / h# 修改偏移量
h=0.1
for i in range(10):print(f'h={h:.5f}.時的函數值為{f(h):.5f},導數值為{numerical_lim(f,1,h):.8f}')h*=0.1
這里先定義了原函數:
def f(x):
return 3x**2-3x
然后定義了原函數的導數:
def numerical_lim(f, x, h):
return (f(x + h) - f(x)) / h
最后通過改變自變量偏移量的形式,不斷逼近導數的真實值:
h=0.1 for i in range(10):
print(f’h={h:.5f}.時的函數值為{f(h):.5f},導數值為{numerical_lim(f,1,h):.8f}')
h*=0.1
代碼運行后的效果為:
可見,隨著偏移量的減小,在x=1位置處,函數f(x)的導數值不斷趨向準確值3。
細節說明
由于小數位數的限制,如果繼續減小h到h=0.000 000 000 000 000 100,函數f(x)的值和導數值都會變成0。
對此有兩種解釋:
- x此時本身是無窮小量,在f(x)=3x**2-3x中,極小的x計算了平方后,已經遠遠小于x本身,函數f(x)的值和導數值都是無窮小量,計算效果輸出0。
- Python 的 float 類型使用 IEEE 754 雙精度 64 位浮點數,提供約15-17位十進制有效數字,一旦超出就可能不準。h=0.000000000000000100的1出現在第16位,此時的計算結果就會出現不準。
可運行此時的代碼測試:
h = 0.1234567
print(f'h當前值:{h}')
print(f'h當前值(1位小數):{h:.1f}')
print(f'h當前值(3位小數):{h:.3f}')
print(f'h當前值(5位小數):{h:.5f}')
print(f'h當前值(8位小數):{h:.8f}')
print(f'h當前值(10位小數):{h:.10f}')
for i in range(5):print(f'h當前值保留{i}位小數:{h:.{i}f}')# 定義原函數
def f(x):return 3*x**2-3*x# 定義求導函數
def numerical_lim(f, x, h):return (f(x + h) - f(x)) / h# 修改偏移量
h=0.1
for i in range(20):print(f'i={i},h={h:.18f}.時的函數值為{f(h):.18f},導數值為{numerical_lim(f,1,h):.18f}')h*=0.1
總結
學習了pytorch導數運算和相關的f-string使用方法。