本文非常全面的介绍了Scipy库,希望大家有耐心的看下去。参考链接在最后。
目录:
1. Scipy简介
1.1 子包
1.2 数据结构
2. Scipy开发环境安装
2.1 Windows
2.2 Linux
3. Scipy基本功能
3.1 内在Numpy数组创建
3.2 矩阵
4. Scipy簇聚
4.1 Scipy中实现K-Means
4.2 三个集群计算K均值
5. Scipy常量
5.1 Scipy常量包
5.2 可用常量列表
6. FFTpack
6.1 快速傅立叶变换
6.2 离散余弦变换
7. 积分
7.1 单积分
7.2 多重积分
7.3 双重积分
8. 插值
8.1 插值是什么
8.2 一线插值
8.3 样条曲线
9. 输入/输出
10. Linalg
10.1 线性方程组
10.2 查找行列式
10.3 特征向量与特征值
11. Ndimage
11.1 打开与写入图像文件
11.2 滤镜
11.3 边缘检测
12. 优化算法
12.1 Nelder-Mead单纯形算法
12.2 最小二乘
13. 统计函数
14. CSGraph
15. Scipy空间
16. Scipy ODR
17. Scipy特殊包
----------------------------------------------------------------------------------
7. Scipy积分
当一个函数不能被分析积分,或者很难分析积分时,通常会转向数值积分方法。 SciPy有许多用于执行数值积分的程序。 它们中的大多数都在同一个scipy.integrate库中。 下表列出了一些常用函数。
7.1 单积分
Quad函数是SciPy积分函数的主力。 数值积分有时称为正交积分,因此称为名称。 它通常是在a到b给定的固定范围内执行函数f(x)的单个积分的默认选择。
quad的一般形式是scipy.integrate.quad(f,a,b),其中'f'是要积分的函数的名称。 而'a'和'b'分别是下限和上限。 下面来看看一个高斯函数的例子,它的积分范围是0和1。
首先需要定义这个函数:
这可以使用lambda表达式完成,然后在该函数上调用四方法。
import scipy.integrate
from numpy import exp
f=lambdax:exp(-x**2)
i=scipy.integrate.quad(f,0,1)
print(i)
执行上面示例代码,得到以下结果 -
(0.7468241328124271, 8.291413475940725e-15)
四元函数返回两个值,其中第一个数字是积分值,第二个数值是积分值绝对误差的估计值。
注 - 由于quad需要函数作为第一个参数,因此不能直接将exp作为参数传递。 Quad函数接受正和负无穷作为限制。 Quad函数可以积分单个变量的标准预定义NumPy函数,如exp,sin和cos。
7.2 多重积分
双重和三重积分的机制已被包含到函数dblquad,tplquad和nquad中。 这些函数分别积分了四个或六个参数。 所有内积分的界限都需要定义为函数。
7.3 双重积分
dblquad的一般形式是scipy.integrate.dblquad(func,a,b,gfun,hfun)。 其中,func是要积分函数的名称,'a'和'b'分别是x变量的下限和上限,而gfun和hfun是定义变量y的下限和上限的函数名称。
看看一个执行双重积分方法的示例。
使用lambda表达式定义函数f,g和h。 请注意,即使g和h是常数,它们可能在很多情况下必须定义为函数,正如在这里为下限所做的那样。
import scipy.integrate
from numpy import exp
from math import sqrt
f=lambdax,y:16*x*y
g=lambdax:0
h=lambday:sqrt(1-4*y**2)
i=scipy.integrate.dblquad(f,0,0.5,g,h)
print(i)
执行上面示例代码,得到以下结果 -
(0.5, 1.7092350012594845e-14)
除上述例程外,scipy.integrate还有许多其他积分的程序,其中包括执行n次多重积分的nquad以及实现各种集成算法的其他例程。 但是,quad和dblquad将满足对数值积分的大部分需求。
8. Scipy插值
8.1 插值是什么?
插值是在直线或曲线上的两点之间找到值的过程。 为了帮助记住它的含义,我们应该将“inter”这个词的第一部分想象为“输入”,表示要查看原来数据的“内部”。 这种插值工具不仅适用于统计学,而且在科学,商业或需要预测两个现有数据点内的值时也很有用。
下面创建一些数据,看看如何使用scipy.interpolate包进行插值。
import numpy as np
from scipy import interpolate
import matplotlib.pyplot as plt
x=np.linspace(0,4,12)
y=np.cos(x**2/3+4)
print(x,y)
执行上面示例代码,得到以下结果 -
[ 0. 0.36363636 0.72727273 1.09090909 1.45454545 1.81818182
2.18181818 2.54545455 2.90909091 3.27272727 3.63636364 4. ] [-0.65364362 -0.61966189 -0.51077021 -0.31047698 -0.00715476 0.37976236
0.76715099 0.99239518 0.85886263 0.27994201 -0.52586509 -0.99582185]
现在,有两个数组。 假设这两个数组作为空间点的两个维度,使用下面的程序进行绘图,并看看它们的样子。
plt.plot(x,y,’o’)
plt.show()
上述程序将生成以下输出 -
8.2 一维插值
scipy.interpolate中的interp1d类是一种创建基于固定数据点的函数的便捷方法,可以使用线性插值在给定数据定义的域内的任意位置评估该函数。
通过使用上述数据,创建一个插值函数并绘制一个新的插值图。
f1=interp1d(x,y,kind='linear')
f2=interp1d(x,y,kind='cubic')
使用interp1d函数,创建了两个函数f1和f2。 这些函数对于给定的输入x返回y。 第三种变量类型表示插值技术的类型。 ‘线性’,’最近’,’零’,’线性’,’二次’,’立方’是一些插值技术。
现在,创建更多长度的新输入以查看插值的明显区别。 对新数据使用旧数据的相同功能。
xnew=np.linspace(0,4,30)
plt.plot(x,y,'o',xnew,f1(xnew),'-',xnew,f2(xnew),'--')
plt.legend(['data','linear','cubic','nearest'],loc='best')
plt.show()
上述程序将生成以下输出 -
8.3 样条曲线
为了通过数据点画出平滑的曲线,绘图员曾经使用薄的柔性木条,硬橡胶,金属或塑料称为机械样条。 为了使用机械花键,在设计中沿着曲线明确选择了一些销钉,然后将花键弯曲,以便它们接触到每个销钉。
显然,在这种结构下,样条曲线在这些引脚上插入曲线。 它可以用来在其他图纸中重现曲线。 引脚所在的点称为结。 可以通过调整结点的位置来改变样条线所定义的曲线的形状。
单变量样条
一维平滑样条拟合一组给定的数据点。Scipy.interpolate中的UnivariateSpline类是创建基于固定数据点类的函数的便捷方法 -scipy.interpolate.UnivariateSpline(x,y,w = None,bbox = [None,None],k = 3,s = None,ext = 0,check_finite = False)。
下面来看看一个例子。
import matplotlib.pyplot as plt
from scipy.interpolate import UnivariateSpline
x=np.linspace(-3,3,50)
y=np.exp(-x**2)+0.1*np.random.randn(50)
plt.plot(x,y,'ro',ms=5)
plt.show()
使用平滑参数的默认值。效果如下 -
spl=UnivariateSpline(x,y)
xs=np.linspace(-3,3,1000)
plt.plot(xs,spl(xs),'g',lw=3)
plt.show()
手动更改平滑量。效果如下 -
spl.set_smoothing_factor(0.5)
plt.plot(xs,spl(xs),'b',lw=3)
plt.show()
效果如下 -
9. 输入/输出
http://Scipy.io包提供了多种功能来解决不同格式的文件(输入和输出)。 其中一些格式是 -
Matlab
IDL
Matrix Market
Wave
Arff
Netcdf等
这里讨论最常用的文件格式 -
MATLAB
以下是用于加载和保存.mat文件的函数。
让我们来看看下面的例子。
import http://scipy.io as sio
import numpy as np
#Save a mat file
vect=np.arange(10)
sio.savemat('array.mat',{'vect':vect})
#Now Load the File
mat_file_content=sio.loadmat('array.mat')
print(mat_file_content)
上述程序将生成以下输出 -
{
'vect': array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]), '__version__': '1.0',
'__header__': 'MATLAB 5.0 MAT-file Platform: posix, Created on: Sat Sep 30
09:49:32 2017', '__globals__': []
}
可以看到数组以及元信息。 如果想在不读取数据到内存的情况下检查MATLAB文件的内容,请使用如下所示的whosmat命令。
import http://scipy.io as sio
mat_file_content=sio.whosmat(‘array.mat’)
print(mat_file_content)
上述程序将生成以下输出。
[('vect', (1, 10), 'int64')]
10. Scipy Linalg
SciPy是使用优化的ATLAS LAPACK和BLAS库构建的。 它具有非常快的线性代数能力。 所有这些线性代数例程都需要一个可以转换为二维数组的对象。 这些例程的输出也是一个二维数组。
SciPy.linalg与NumPy.linalg
scipy.linalg包含numpy.linalg中的所有函数。 另外,scipy.linalg还有一些不在numpy.linalg中的高级函数。 在numpy.linalg上使用scipy.linalg的另一个优点是它总是用BLAS/LAPACK支持编译,而对于NumPy,这是可选的。 因此,根据NumPy的安装方式,SciPy版本可能会更快。
10.1 线性方程组
scipy.linalg.solve特征为未知的x,y值求解线性方程a * x + b * y = Z。
作为一个例子,假设需要解下面的联立方程。
要求解x,y,z值的上述方程式,可以使用矩阵求逆来求解向量,如下所示。
但是,最好使用linalg.solve命令,该命令可以更快,更稳定。
求解函数采用两个输入'a'和'b',其中'a'表示系数,'b'表示相应的右侧值并返回解矩阵。
现在来看看下面的例子。
#importing the scipy and numpy packages
from scipy import linalg
import numpy as np
#Declaring the numpy arrays
a=np.array([[3,2,0],[1,-1,0],[0,5,1]])
b=np.array([2,4,-1])
#Passing the values to the solve function
x=linalg.solve(a,b)
#printing the result array
print(x)
执行上面示例代码,得到以下结果 -
[ 2. -2. 9.]
Shell
10.2 查找一个行列式
方阵A的行列式通常表示为| A |并且是线性代数中经常使用的量。 在SciPy中,这是使用det()函数计算的。 它将矩阵作为输入并返回一个标量值。
下面来看看一个例子。
#importing the scipy and numpy packages
from scipy import linalg
import numpy as np
#Declaring the numpy array
A=np.array([[1,2],[3,4]])
#Passing the values to the det function
x=linalg.det(A)
#printing the result
print(x)
执行上面示例代码,得到以下结果 -
-2.0
10.3 特征值和特征向量
特征值 - 特征向量问题是最常用的线性代数运算之一。 我们可以通过考虑以下关系式来找到方阵(A)的特征值(λ)和相应的特征向量(v)
Av = λv
scipy.linalg.eig从普通或广义特征值问题计算特征值。 该函数返回特征值和特征向量。
让我们来看看下面的例子。
#importing the scipy and numpy packages
from scipy import linalg
impor tnumpy as np
#Declaring the numpy array
A=np.array([[1,2],[3,4]])
#Passing the values to the eig function
l,v=linalg.eig(A)
#printing the result for eigen values
print(l)
#printing the result for eigen vectors
print(v)
执行上面示例代码,得到以下结果 -
[-0.37228132+0.j 5.37228132+0.j]
[[-0.82456484 -0.41597356]
[ 0.56576746 -0.90937671]]
10.4 奇异值分解
奇异值分解(SVD)可以被认为是特征值问题扩展到非矩阵的矩阵。
scipy.linalg.svd将矩阵'a'分解为两个酉矩阵'U'和'Vh',以及一个奇异值(实数,非负)的一维数组's',使得a == U * S * Vh,其中'S'是具有主对角线's'的适当形状的零点矩阵。
让我们来看看下面的例子。参考以下代码 -
#importing the scipy and numpy packages
from scipy import linalg
import numpy as np
#Declaring the numpy arraya=np.random.randn(3,2)+1.j*np.random.randn(3,2)
#Passing the values to the eig function
U,s,Vh=linalg.svd(a)
# printing the result
print(U,Vh,s)
执行上面示例代码,得到以下结果 -
[[-0.60142679+0.28212127j 0.35719830-0.03260559j 0.61548126-0.22632383j]
[-0.00477296+0.44250532j 0.64058557+0.15734719j -0.40414313+0.45357092j]
[ 0.46360086+0.38462177j -0.18611686+0.6337182j 0.44311251+0.06747886j]] [[ 0.98724353+0.j -0.01113675+0.15882756j]
[-0.15921753+0.j -0.06905445+0.9848255j ]] [ 2.04228408 1.33798044]
11. Scipy Ndimage
SciPy的ndimage子模块专用于图像处理。这里,ndimage表示一个n维图像。
图像处理中一些最常见的任务如下:
输入/输出,显示图像
基本操作 - 裁剪,翻转,旋转等
图像过滤 - 去噪,锐化等
图像分割 - 标记对应于不同对象的像素
分类
特征提取
注册/配准
下面来看看如何使用SciPy实现其中的一些功能。
11.1 打开和写入图像文件
SciPy中的misc包附带了一些图像。在这里,使用这些图像来学习图像操作。请看看下面的例子。
from scipy import misc
f=misc.face()misc.imsave('face.png',f) # uses the Image module (PIL)
import matplotlib.pyplot as plt
plt.imshow(f)
plt.show()
执行上面示例代码,得到以下输出结果 -
原始格式的任何图像是由矩阵格式中的数字表示的颜色的组合。机器只能根据这些数字理解和操作图像。RGB是一种流行的表示方式。
下面来看看上面图片的统计信息。
from scipy import misc
f=misc.face()misc.imsave('face.png',f) # uses the Image module (PIL)
face=misc.face(gray=False)
print(face.mean(),face.max(),face.min())
执行上面示例代码,得到以下结果 -
110.162743886 255 0
现在,我们已经知道图像是由数字组成的,所以数字值的任何变化都会改变原始图像。接下来对图像执行一些几何变换。基本的几何操作是裁剪 -
from scipy import misc
f=misc.face()misc.imsave('face.png',f)# uses the Image module (PIL)
face=misc.face(gray=True)
lx,ly=face.shape
crop_face=face[int(lx/4):-int(lx/4),int(ly/4):-int(ly/4)]
import matplotlib.pyplot as plt
plt.imshow(crop_face)
plt.show()
执行上面示例代码,得到以下结果 -
也可以执行一些基本的操作,例如像下面描述的那样倒置图像。参考以下代码 -
from scipy import misc
face=misc.face()
flip_ud_face=np.flipud(face)
import matplotlib.pyplot as plt
plt.imshow(flip_ud_face)
plt.show()
执行上面示例代码,得到以下结果 -
除此之外,还有rotate()函数,它以指定的角度旋转图像。
#rotation
from scipy import misc,ndimage
face=misc.face()
rotate_face=ndimage.rotate(face,45)
import matplotlib.pyplot as plt
plt.imshow(rotate_face)
plt.show()
执行上面示例代码,得到以下结果 -
11.2 滤镜
下面来看看滤镜如何应用在图像处理中。
图像处理中的滤镜是什么?
滤镜是一种修改或增强图像的技术。例如,可以过滤图像以强调某些功能或删除其他功能。通过滤镜实现的图像处理操作包括平滑,锐化和边缘增强。
滤镜是一种邻域操作,其中输出图像中任何给定像素的值是通过对相应输入像素的邻域中的像素的值应用某种算法来确定的。现在使用SciPy ndimage执行一些操作。
模糊
模糊广泛用于减少图像中的噪声。可以执行过滤操作并查看图像中的更改。看看下面的例子。
from scipy import misc
face=misc.face()
blurred_face=ndimage.gaussian_filter(face,sigma=3)
import matplotlib.pyplot as plt
plt.imshow(blurred_face)
plt.show()
执行上面示例代码,得到以下结果 -
sigma值表示5级模糊程度。通过调整sigma值,可以看到图像质量的变化。
11.3 边缘检测
讨论边缘检测如何帮助图像处理。
什么是边缘检测?
边缘检测是一种用于查找图像内物体边界的图像处理技术。它通过检测亮度不连续性来工作。边缘检测用于诸如图像处理,计算机视觉和机器视觉等领域的图像分割和数据提取。
最常用的边缘检测算法包括 -
索贝尔(Sobel)
坎尼(Canny)
普鲁伊特(Prewitt)
罗伯茨Roberts
模糊逻辑方法
看看下面的一个例子。
import scipy.ndimage as nd
import numpy as np
im=np.zeros((256,256))
im[64:-64,64:-64]=1
im[90:-90,90:-90]=2
im=ndimage.gaussian_filter(im,8)
import matplotlib.pyplot as plt
plt.imshow(im)
plt.show()
执行上面示例代码,得到以下结果 -
图像看起来像一个方块的颜色。现在,检测这些彩色块的边缘。这里,ndimage提供了一个叫Sobel函数来执行这个操作。而NumPy提供了Hypot函数来将两个合成矩阵合并为一个。
看看下面的一个例子。参考以下实现代码 -
import scipy.ndimage as nd
import matplotlib.pyplot as plt
im=np.zeros((256,256))
im[64:-64,64:-64]=1
im[90:-90,90:-90]=2
im=ndimage.gaussian_filter(im,8)
sx=ndimage.sobel(im,axis=0,mode='constant')
sy=ndimage.sobel(im,axis=1,mode='constant')
sob=np.hypot(sx,sy)
plt.imshow(sob)
plt.show()
执行上面示例代码,得到以下结果 -
12. Scipy优化算法
scipy.optimize包提供了几种常用的优化算法。 该模块包含以下几个方面 -
使用各种算法(例如BFGS,Nelder-Mead单纯形,牛顿共轭梯度,COBYLA或SLSQP)的无约束和约束最小化多元标量函数(minimize())
全局(蛮力)优化程序(例如,anneal(),basinhopping())
最小二乘最小化(leastsq())和曲线拟合(curve_fit())算法
标量单变量函数最小化(minim_scalar())和根查找(newton())
使用多种算法(例如,Powell,Levenberg-Marquardt混合或Newton-Krylov等大规模方法)的多元方程系统求解(root)
多变量标量函数的无约束和约束最小化
minimize()函数为scipy.optimize中的多变量标量函数提供了无约束和约束最小化算法的通用接口。 为了演示最小化函数,考虑使NN变量的Rosenbrock函数最小化的问题 -
这个函数的最小值是0,当xi = 1时达到。
12.1 Nelder–Mead单纯形算法
在下面的例子中,minimize()例程与Nelder-Mead单纯形算法(method ='Nelder-Mead')一起使用(通过方法参数选择)。参考下面的例子。
import numpy as np
from scipy.optimize import minimize
def rosen(x):
x0=np.array([1.3,0.7,0.8,1.9,1.2])
res=minimize(rosen,x0,method='nelder-mead')
print(res.x)
上述程序将生成以下输出 -
[7.93700741e+54-5.41692163e+536.28769150e+531.38050484e+55-4.14751333e+54]
简单算法只需要函数评估,对于简单的最小化问题是一个不错的选择。 但是,由于它不使用任何梯度评估,因此可能需要较长时间才能找到最小值。
另一种只需要函数调用来寻找最小值的优化算法就是鲍威尔方法,它可以通过在minimize()函数中设置method ='powell'来实现。
12.2 最小二乘
求解一个带有变量边界的非线性最小二乘问题。 给定残差f(x)(n个实变量的m维实函数)和损失函数rho(s)(标量函数),最小二乘法找到代价函数F(x)的局部最小值。 看看下面的例子。
在这个例子中,Rosenbrock函数的最小值不受自变量的限制。
#Rosenbrock Function
def fun_rosenbrock(x):
returnnp.array([10*(x[1]-x[0]**2),(1-x[0])])
from scipy.optimize import least_squares
input=np.array([2,2])
res=least_squares(fun_rosenbrock,input)
print(res)
请注意,我们只提供残差的向量。 该算法将成本函数构造为残差的平方和,这给出了Rosenbrock()函数。 确切的最小值是x = [1.0,1.0]。
上述程序将生成以下输出 -
active_mask:array([0.,0.])
cost:9.8669242910846867e-30
fun:array([4.44089210e-15,1.11022302e-16])
grad:array([-8.89288649e-14,4.44089210e-14])
jac:array([[-20.00000015,10.],[-1.,0.]])
message:'`gtol` termination condition is satisfied.'
nfev:3
njev:3
optimality:8.8928864934219529e-14
status:1
success:True
x:array([1.,1.])
12.3 求根
让我们了解求根如何在SciPy中使用。
标量函数
如果有一个单变量方程,则可以尝试四种不同的寻根算法。 这些算法中的每一个都需要预期根的时间间隔的端点(因为函数会改变符号)。 一般来说,brentq是最好的选择,但其他方法可能在某些情况下或学术目的有用。
定点求解
与找到函数零点密切相关的问题是找到函数的固定点的问题。 函数的固定点是函数评估返回点的点:g(x)= x。 显然,gg的不动点是f(x)= g(x)-x的根。 等价地,ff的根是g(x)= f(x)+ x的固定点。 例程fixed_point提供了一个简单的迭代方法,使用Aitkens序列加速度来估计gg的固定点,如果给出起点的话。
方程组
使用root()函数可以找到一组非线性方程的根。 有几种方法可供选择,其中hybr(默认)和lm分别使用Powell的混合方法和MINPACK中的Levenberg-Marquardt方法。
下面的例子考虑了单变量超越方程。
其根可以求解如下 -
import numpy as np
from scipy.optimize import root
def func(x):
returnx*2+2*np.cos(x)
sol=root(func,0.3)
print(sol)
执行上面示例代码,得到以下结果 -
fjac: array([[-1.]])
fun: array([ 2.22044605e-16])
message: 'The solution converged.'
nfev: 10
qtf: array([ -2.77644574e-12])
r: array([-3.34722409])
status: 1
success: True
x: array([-0.73908513])