前言:
本文需要同学们掌握一定的python基础,如果你对python和Numpy不是很了解,请先移步上面的Python和Numpy教程。
1. 概述
SciPy是什么?
SciPy 是基于 Python 的一个开源软件库,用于科学计算和技术计算。它构建在 NumPy 数组对象之上(这里值得一提的是它是在 NumPy 的基础上构建的,因此继承了 NumPy 高效处理大型数据数组的能力),使得它能够有效地操作和处理大型数组或矩阵。SciPy 提供了许多模块,涵盖了不同的科学计算领域,如线性代数、优化、积分、插值、特殊函数、快速傅立叶变换、信号处理和图像处理等。
SciPy 是科学 Python 生态系统的核心组件之一,与 NumPy、Matplotlib(一种绘图库)、Pandas(一种数据分析库)等库一起,为科学计算提供了一个强大的环境。(很牛的一个库)
可以用来解决最优化、线性代数、积分、插值、特殊函数、快速傅里叶变换、信号处理和图像处理、常微分方程求解等问题(和MATLAB很像)
2.SciPy历史
SciPy库是科学计算中最重要的Python库之一,它的发展经历了多个阶段,结合了许多科研人员的贡献。SciPy的故事从这里开始~
SciPy的起源
- 1999年:
SciPy的最初版本由Travis Oliphant创建,基于另一个名为"Multipack"的科学计算包,其本身就是许多基于Fortran库的接口集合(如ODRPACK, QUADPACK, FITPACK 等)。 - 2001年:
SciPy的官方版本0.1发布。此时,SciPy已经集成了许多标准的科学计算功能。
重要的发展阶段
- 2005年:
NumPy的诞生对SciPy发展非常关键。早期SciPy使用的数组对象是Numeric库,而Travis Oliphant推动创建了NumPy以统一Python中的数组类型,从而更好地支持SciPy的需求。之后,SciPy完全迁移至NumPy作为其数组处理的基础。 - 2006年以后:
开始形成了稳定的发展模式,更多的开发者加入,社区渐渐壮大。随着时间的推移,增加了更多的子模块和功能,比如稀疏矩阵的处理、信号处理工具、优化算法等。
社区与扩展
- 2010年代:
SciPy社区逐渐成熟,通过定期的国际会议(如SciPy会议)、教程和文档,为用户提供支持和学习资源。这一时期,SciPy与其他科学计算库一起,如Pandas和Matplotlib,构建了强大的Python数据科学生态系统。 - 至今:
SciPy不断更新和完善,每个新版本都添加了新功能和性能改进,保持与Python和NumPy的兼容性。此外,随着Python的流行和AI技术的兴起,SciPy库在科学、工程、数据分析和机器学习领域越来越受欢迎。
版本更新
- SciPy 1.0:
2017年,十六年后的努力 culminated in the release of SciPy 1.0,标志着一个成熟、稳定和功能丰富的科学计算库的成就。
3.安装
安装命令为
pip install scipy
通常,安装 SciPy 还会要求你系统中已经安装了 NumPy,所以做数据分析的时候最好相关的库都准备一下
4.常用功能使用
首先我们检查一下安装好了没有,顺便看一下版本号
import scipy
print(scipy.__version__)
这时你会看到在终端类似这样的输出
然后我们开始学习一些常用的函数
4.1 常用的函数
scipy.integrate: 这个模块提供了数值积分和常微分方程求解器。
from scipy.integrate import quad
# 定义一个函数
def integrand(x):
return x**2
# 计算从0到1的积分
result, error = quad(integrand, 0, 1)
print("积分结果:", result,"误差:", error)
输出结果为
这里解释一下为什么有误差
数值积分方法在计算定积分时,需要对被积函数进行离散化,即将连续的函数值用离散的点来表示。这种离散化会导致一定的误差,因为实际函数在离散点处的值可能与实际值有差异。
scipy.linalg
:涵盖了线性代数的基础和高级功能。
import numpy as np
from scipy import linalg
# 创建一个矩阵
A = np.array([[1, 2], [3, 4]])
# 计算矩阵的逆
inv_A = linalg.inv(A)
# 创建一个向量
b = np.array([5, 6])
# 计算A的逆乘以向量b
x = np.dot(inv_A, b)
print(x)
scipy.optimize
:提供了函数最小化、曲线拟合和求根的算法。
from scipy import optimize
def objective_function(x):
return x**2
result = optimize.minimize(objective_function, x0=1, method="BFGS")
print(result.x) # 输出最小值点
scipy.sparse
:包含了稀疏矩阵的数据结构以及相关的快速运算。
from scipy import sparse
# 创建一个稀疏矩阵
A = sparse.csr_matrix(([1, 2, 3], [0, 1, 2], [1, 0, 0]), shape=(3, 3))
# 计算矩阵的逆
inv_A = A.inv()
# 打印稀疏矩阵的逆
print(inv_A.toarray())
scipy.interpolate
:为数据点提供多种插值工具和算法。
import numpy as np
from matplotlib import pyplot as plt
from scipy import interpolate
x = [1, 2, 3, 4, 5]
y = [2, 3, 5, 7, 11]
# 创建一个插值函数
f = interpolate.interp1d(x, y, kind="linear")
# 计算插值函数在特定点的值
print(f(3.5))
# 创建一个插值函数,并绘制原始数据和插值曲线
xnew = np.linspace(1, 5, 100)
ynew = f(xnew)
plt.plot(x, y, "o", xnew, ynew, "-")
plt.show()
scipy.fftpack
:提供了快速傅里叶变换的工具。
from scipy import fftpack
# 创建一个信号
signal = [1, 2, 3, 4, 5]
# 计算信号的傅里叶变换
fourier_transform = fftpack.fft(signal)
# 打印傅里叶变换的结果
print(fourier_transform)
scipy.stats
:包含大量的概率分布和统计函数。
from scipy import stats
# 创建一个正态分布的随机变量
random_variable = stats.norm.rvs(size=100)
# 计算随机变量的均值和标准差
mean = random_variable.mean()
std_dev = random_variable.std()
print("Mean:", mean)
print("Standard Deviation:", std_dev)
常用的函数:
scipy.integrate
:提供了数值积分例程和微分方程求解器。scipy.linalg
:涵盖了线性代数的基础和高级功能。scipy.optimize
:提供了函数最小化、曲线拟合和求根的算法。scipy.sparse
:包含了稀疏矩阵的数据结构以及相关的快速运算。scipy.interpolate
:为数据点提供多种插值工具和算法。scipy.fftpack
:提供了快速傅里叶变换的工具。scipy.stats
:包含大量的概率分布和统计函数。
4.2 不同分区整理
数学、科学和工程计算
scipy.cluster 向量量化
from scipy.cluster.vq import vq
# 定义一个向量列表
vectors = [
[1, 2],
[3, 4],
[5, 6],
[7, 8],
[9, 10]
]
# 使用vq函数计算每个向量对应的码书(quantization codebook)
codebooks, _ = vq(vectors, vectors)
# 输出码书
print(codebooks)
使用了 scipy.cluster.vq 模块中的 vq 函数,用于向量量化(图像处理和计算机视觉领域常用`)
scipy.constants 数学常量
import scipy.constants as const
# 输出圆周率
print(const.pi)
# 输出光速
print(const.c)
# 输出库仑常数
print(const.e)
# 输出阿伏加德罗常数
print(const.N_A)
scipy.constants 模块提供了许多数学和物理常量,例如圆周率、光速、库仑常数和阿伏加德罗常数等
# scipy.fft 快速傅里叶变换
import numpy as np
from scipy.fft import fft, ifft
# 创建一个信号
x = np.linspace(0, 1, 1000)
y = np.sin(2 * np.pi * 10 * x) + np.sin(2 * np.pi * 50 * x)
# 计算信号的快速傅里叶变换
Y = fft(y)
# 计算信号的逆快速傅里叶变换
y_inv = ifft(Y)
# 输出原始信号和恢复的信号
print("Original signal:", y)
print("Recovered signal:", y_inv)
这里注意:fft 和 ifft 函数返回的是 complex 数组
# scipy.io 数据输入输出
from scipy.io import loadmat, savemat
# 加载 .mat 文件
mat_data = loadmat('data.mat')
# 打印加载的 .mat 文件数据
print(mat_data)
# 创建一个字典用于保存 .mat 文件
mat_dict = {'key1': [[1, 2], [3, 4]], 'key2': [5, 6]}
# 保存 .mat 文件
savemat('output.mat', mat_dict)
.mat 文件的加载和保存,这里搭配MATLAB食用更佳
# scipy.linalg 线性代数
import numpy as np
from scipy.linalg import det, inv, pinv, solve, sqrtm
# 创建一个矩阵
A = np.array([[1, 2], [3, 4]])
# 计算矩阵的行列式
print("Determinant of A:", det(A))
# 计算矩阵的逆
A_inv = inv(A)
print("Inverse of A:\n", A_inv)
# 计算矩阵的伪逆
A_pinv = pinv(A)
print("Pseudo-inverse of A:\n", A_pinv)
# 解线性方程组
b = np.array([1, 2])
x = solve(A, b)
print("Solution of A * x = b:", x)
# 计算矩阵的平方根
A_sqrt = sqrtm(A)
print("Square root of A:\n", A_sqrt)
和MATLAB很像,不过这里注意这些函数返回的是数组,如果需要返回标量,可以使用函数的 scalar 版本,例如 det(A).item()。
# scipy.misc 图像处理
from scipy.misc import ascent, imread, imresize, imshow
# 加载图像
img = imread('image.jpg')
# 显示图像
imshow(img)
# 调整图像大小
img_resized = imresize(img, (100, 100))
# 显示调整大小后的图像
imshow(img_resized)
scipy.misc 模块提供了许多用于图像处理的函数,例如加载、调整大小和显示图像等。这里注意imread 函数返回的是一个 NumPy 数组(NumPy 数组是一个包含同类型数据的数据结构,可以用来存储列表、列表的列表(矩阵)、列表的列表的列表(三维数组)等)
# scipy.special 特殊数学函数
from scipy.special import gamma, loggamma, erf, exp1, log1p
# 计算伽马函数
print("Gamma function at 2:", gamma(2))
# 计算对数伽马函数
print("Logarithm of Gamma function at 2:", loggamma(2))
# 计算误差函数
print("Error function at 2:", erf(2))
# 计算exp1函数
print("exp1 function at 2:", exp1(2))
# 计算log1p函数
print("log1p function at 2:", log1p(2))
还是一样,函数返回的是数组
5.scipy
进阶 - 显著性检验
前言 什么是显著性检验
显著性检验是统计学中的一种方法,用于确定两个或多个数据集之间的差异是否显著,即是否由于真实差异而不是随机变异导致的。它通常用于比较两组数据或者评估一个模型的性能是否显著地优于另一个模型。
在进行显著性检验时,我们首先提出一个假设,称为原假设(null hypothesis),通常表示没有差异或效应。然后收集数据,利用统计学方法计算一种统计量,例如 t 值、z 值或 F 值,来评估观察到的数据与原假设之间的差异。
接着,我们确定一个显著性水平(significance level),通常用 α 表示,来指定接受或拒绝原假设的临界值。如果计算得到的统计量的 p 值小于显著性水平,通常是 α 值(通常为 0.05),则我们拒绝原假设,认为观察到的差异是显著的;否则,我们接受原假设,认为差异不显著。
t 检验 : 是一种用于比较两个样本均值是否有显著差异的统计方法
from scipy import stats
# 假设我们有两个样本
sample1 = [1, 2, 3, 4, 5]
sample2 = [2, 4, 6, 8, 10]
# 进行t检验
t_statistic, p_value = stats.ttest_ind(sample1, sample2)
# 打印结果
print("t statistic:", t_statistic)
print("p value:", p_value)
# 如果p值小于0.05,我们可以拒绝原假设,即认为两个样本来自不同的总体。
# 如果p值大于0.05,我们不能拒绝原假设,即认为两个样本来自相同的总体。
KS 检验(Kolmogorov-Smirnov test):是一种非参数统计方法,用于比较两个样本的累积分布函数是否有显著差异。
from scipy import stats
# 假设我们有两个样本
sample1 = [1, 2, 3, 4, 5]
sample2 = [2, 4, 6, 8, 10]
# 计算两个样本的KS统计量
ks_statistic, p_value = stats.ks_2samp(sample1, sample2)
# 打印结果
print("KS statistic:", ks_statistic)
print("p value:", p_value)
# 如果p值小于0.05,我们可以拒绝原假设,即认为两个样本来自不同的总体。
# 如果p值大于0.05,我们不能拒绝原假设,即认为两个样本来自相同的总体。
正态性检验 :是用于检验数据是否符合正态分布的统计方法
from scipy import stats
# 假设我们有一个样本
sample = [1, 2, 3, 4, 5]
# 计算样本的Shapiro-Wilk统计量和p值
shapiro_wilk_statistic, p_value = stats.shapiro(sample)
# 打印结果
print("Shapiro-Wilk statistic:", shapiro_wilk_statistic)
print("p value:", p_value)
# 如果p值小于0.05,我们可以拒绝原假设,即认为样本不服从正态分布。
# 如果p值大于0.05,我们不能拒绝原假设,即认为样本服从正态分布。
写在最后
更多详细内容可以到这里SciPy -