机器学习之sympy库对于函数的基本操作

一.前言

sympy是一个符号计算系统
符号计算:数学对象是精确表示的,而不是近似的,并且具有未计算变量的数学表达式以符号形式保留
举个例子:
使用python自带数学函数计算库math计算sqrt(8)

import math
math.sqrt(8)

输出:2.82842712475

使用sympy库计算sqrt(8)

import sympy
sympy.sqrt(8)

输出:2*sqrt(2)

总结:
对于math库是求值,如果求不出精确值就求近似
对于 sympy库求值,如果求不出精确值就以符号形式表示

二.sympy库基本函数使用

1.基础函数

1.1.symbols函数

sympy.symbols() 用于创建符号变量的函数。
定义数学表达式中的未知数,比如变量 x, y 等。

实例代码如下:

import sympy
x,y = sympy.symbols('x y')
f_x_y = x+2*y
print(f_x_y)

输出:x+2*y

此时创建了符号变量后,f_x_y可以像数学算式一样进行加减

import sympy
x,y = sympy.symbols('x y')
f_x_y = x+2*y
f_x_y -= x
print(f_x_y )

输出:2*y

1.2.expand函数

用于展开代数表达式,比如把乘法形式的多项式展开。

import sympy
x,y = sympy.symbols("x y")
f_x_y = (x + y)**2
print(sympy.expand(f_x_y))

输出:x**2 + 2*x*y + y**2

1.3.factor函数

用于因式分解代数表达式,把表达式转化为乘法形式。

import sympy
x,y = sympy.symbols("x y")
f_x_y = x**2 + 2*x*y + y**2
print(sympy.factor(f_x_y))

输出:(x + y)**2

2.sympy库的求导函数

2.1diff函数

sympy.diff()
一阶导数

from sympy import symbols, diff
x = symbols('x')
f = x**3 + 2*x**2 + x
df = diff(f, x)
print(df)  # 输出: 3*x**2 + 4*x + 1

输出: 3*x**2 + 4*x + 1

高阶导数

from sympy import symbols, diff,expand
x = symbols('x')
f = x**3 + 2*x**2 + x
df = diff(f, x,2)
print(expand(df))

输出: 6*x + 4

多个变量的偏导数

from sympy import symbols, diff
x, y = symbols('x y')
f = x**2 * y + x * y**2
df_dx = diff(f, x)  # 对 x 求偏导
df_dy = diff(f, y)  # 对 y 求偏导

输出:
2*x*y + y**2 | x**2 + 2*x*y

2.2subs函数

sympy.subs() 是 SymPy 中用来替换表达式中的变量或子表达式的方法

变量代值

from sympy import symbols
x = symbols('x')
expr = x**2 + 2*x + 1
print(expr.subs(x, 3))  

输出:16

变量互换

from sympy import symbols
y = symbols('y')
x = symbols('x')
f = x**2 + 2*x + 1
print(f.subs(x, y))  

输出: y**2 + 2*y + 1

多个同时替换

from sympy import symbols
x, y = symbols('x y')
f = x**2 + y**2
print(f.subs({x: 1, y: 2})) 

输出: 5

2.3solv函数

sympy.solve() 是 SymPy 中用于 **解方程(组)**的函数

解方程

from sympy import symbols, solve, Eq
x = symbols('x')
f = x**2 - 4
print(solve(f, x) )

输出:[-2, 2]

注意:
在数学中,方程的解指的是“让表达式等于 0 的变量值 相当于f(x)=0

三.使用sympy库实现对极小值的求解

1.利用导数为0求极值

代码如下:

import sympy

x = sympy.symbols("x")
y  = x**2
dev = sympy.diff(y,x)      #求导
x_r = sympy.solve(dev,x)   #解方程
y_min = y.subs(x,x_r[0])
print(y_min)

x = sympy.symbols("x")
y  = sympy.sin(x)
dev = sympy.diff(y,x)
x_r = sympy.solve(dev,x)
print(x_r)
y_1 = y.subs(x,x_r[0])
y_2= y.subs(x,x_r[1])
print(y_1,y_2)

2.工程逼近法

工程逼近法是一种基于简化模型、经验数据或数值计算的近似求解方法

我们已经知道 f(x)=x² 的图像
x坐标轴上取一点x,将该点的值带入函数求得y值
假设一个步长step=0.01(步长越小越精确)
将x对步长进行加或减使得y值减小,这样就可以不断逼近于极小值

import sympy
x = sympy.symbols('x')
y = x**2
x_value = 10                        #取一点x
y_value = y.subs(x,x_value)         #求得y值
step = 0.01#设置步长
while 1 :
    x_value  = x_value -step         
    if y.subs(x,x_value)<=y_value:  #判断是否逼近极小值,逼近就继续循环
        y_value = y.subs(x,x_value)
        continue
    else:                           #远离退出循环
        break
print(y_value,x_value)              #得到近似值

3.梯度下降法

数学类比:梯度 = 多维导数
在一维中,导数 f’(x) 是“切线斜率”。
在多维中,梯度 ∇f 就是每个方向的“切线斜率”合集,是一个向量

如图
在这里插入图片描述

如果要找函数的极小值,我们可以用自变量x-导数 f '(x)
为什么呢?
导数 f(x)'相当于点(x , f(x))处做一条切线
此时我们让自变量x-导数 f '(x),重复此操作斜率就如图不断下降,自变量x逼近于极小值x的点,当斜率为0时,自变量x就等于极小值x
根据思路代码如下:

import sympy
import random
x = sympy.symbols('x')
y = x**2
dev = sympy.diff(y,x)
x_value = random.randint(-100,100)    #随机一个起始点
iter = 10000
lr = 0.01                             #学习率 下降的步长
for i in range(iter):
    x_value = x_value - dev.subs(x,x_value)*lr    #逼近
print(y.subs(x,x_value),x_value)

注意:学习率不能为1

拿 ( f(x) = x^2 ) 举例:
函数:
( f(x) = x^2 )
导数:
( f’(x) = 2x )

当 lr = 1 时:
x= x-2x
x=-x
-x = -x+2
x
-x=x
也就是说每一步都变成 “取反”:在不断震荡,无法收敛

所以学习率 lr <1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值