Python 机器学习 基础 之 【常用机器学习库】 NumPy 数值计算库
目录
Python 机器学习 基础 之 【常用机器学习库】 NumPy 数值计算库
一、简单介绍
二、Numpy 基础
1、安装NumPy
2、导入NumPy
3、创建数组
4、数组操作
5、常用函数
6、矩阵运算
7、广播机制
8、随机数
三、在机器学习中使用到 Numpy 的简单示例
1、数据预处理
1.1 数据归一化
1.2 数据标准化
2、特征工程
1.1 多项式特征
3、简单线性回归
3.1 生成数据
3.2 线性回归模型
3.3 预测
4、k-均值聚类
4.1、生成数据
4.2、k-均值算法
一、简单介绍
Python是一种跨平台的计算机程序设计语言。是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越多被用于独立的、大型项目的开发。Python是一种解释型脚本语言,可以应用于以下领域: Web 和 Internet开发、科学计算和统计、人工智能、教育、桌面界面开发、软件开发、后端开发、网络爬虫。
Python 机器学习是利用 Python 编程语言中的各种工具和库来实现机器学习算法和技术的过程。Python 是一种功能强大且易于学习和使用的编程语言,因此成为了机器学习领域的首选语言之一。Python 提供了丰富的机器学习库,如Scikit-learn、TensorFlow、Keras、PyTorch等,这些库包含了许多常用的机器学习算法和深度学习框架,使得开发者能够快速实现、测试和部署各种机器学习模型。
Python 机器学习涵盖了许多任务和技术,包括但不限于:
- 监督学习:包括分类、回归等任务。
- 无监督学习:如聚类、降维等。
- 半监督学习:结合了有监督和无监督学习的技术。
- 强化学习:通过与环境的交互学习来优化决策策略。
- 深度学习:利用深度神经网络进行学习和预测。
通过 Python 进行机器学习,开发者可以利用其丰富的工具和库来处理数据、构建模型、评估模型性能,并将模型部署到实际应用中。Python 的易用性和庞大的社区支持使得机器学习在各个领域都得到了广泛的应用和发展。
二、Numpy 基础
NumPy(Numerical Python)是一个用于科学计算的Python库。它提供了支持大量数据操作和处理的功能,特别是在数值计算领域。NumPy是许多机器学习库的基础,因此了解它是非常重要的。本文将介绍NumPy的基本概念和操作。
1、安装NumPy
在开始之前,请确保已安装NumPy。您可以使用以下命令安装:
pip install numpy
2、导入NumPy
在使用NumPy之前,需要先导入它。通常我们会用np
作为NumPy的别名:
import numpy as np
3、创建数组
NumPy的核心是其ndarray
对象,也就是多维数组。以下是创建数组的一些基本方法:
3.1 从列表创建数组
import numpy as np# 创建一维数组
arr1 = np.array([1, 2, 3, 4, 5])
print(arr1) # 输出结果:[1 2 3 4 5]# 创建二维数组
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(arr2) # 输出结果:
# [[1 2 3]
# [4 5 6]]
在这段代码中,arr1
是一个包含5个整数的一维数组,而arr2
是一个2x3的二维数组,即一个包含两个元素的数组,每个元素本身又是一个包含三个整数的数组。
3.2 使用NumPy内置函数创建数组
import numpy as np# 创建全零数组
zeros = np.zeros((3, 4))
print(zeros) # 输出结果:
# [[0. 0. 0. 0.]
# [0. 0. 0. 0.]
# [0. 0. 0. 0.]]# 创建全一数组
ones = np.ones((2, 3))
print(ones) # 输出结果:
# [[1. 1. 1.]
# [1. 1. 1.]]# 创建一个特定值的数组
full = np.full((2, 2), 7)
print(full) # 输出结果:
# [[7 7]
# [7 7]]# 创建一个单位矩阵
eye = np.eye(3)
print(eye) # 输出结果:
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]# 创建一个等差数组
arange = np.arange(0, 10, 2)
print(arange) # 输出结果:
# [0 2 4 6 8]# 创建一个等间隔数组
linspace = np.linspace(0, 1, 5)
print(linspace) # 输出结果:
# [0. 0.25 0.5 0.75 1. ]
请注意,np.zeros
和np.ones
创建的数组中的元素是浮点数,默认情况下显示为小数点形式。np.full
创建的数组中的元素是整数,如果指定的值是整数的话。np.eye
创建单位矩阵,对角线上的元素是1,其余为0。np.arange
创建一个等差数列,np.linspace
创建一个等间隔的数列。
4、数组操作
4.1 形状操作
import numpy as nparr = np.array([[1, 2, 3], [4, 5, 6]])# 查看数组形状
print(arr.shape) # 输出结果:(2, 3)# 改变数组形状
reshaped = arr.reshape((3, 2))
print(reshaped) # 输出结果:
# [[1 2]
# [3 4]
# [5 6]]
在这段代码中,arr
是一个2x3的二维数组。使用arr.shape
可以查看数组的形状,它返回一个元组,表示数组的维度。然后,使用reshape
方法可以改变数组的形状,reshape((3, 2))
将数组的形状从2x3变为3x2。由于原始数组中只有6个元素,所以reshape
操作是合法的。如果尝试改变形状到一个与原始数组元素总数不匹配的形状,将会引发错误。
4.2 数组索引和切片
import numpy as nparr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])# 索引
print(arr[0]) # 第一个元素: 输出结果:1
print(arr[-1]) # 最后一个元素: 输出结果:9# 切片
print(arr[1:5]) # 从第二个到第五个元素: 输出结果:[2 3 4 5]
print(arr[:3]) # 前三个元素: 输出结果:[1 2 3]
print(arr[::2]) # 每隔一个元素: 输出结果:[1 3 5 7 9]
在这段代码中,arr
是一个包含9个整数的一维数组。通过索引可以访问数组中的单个元素,例如arr[0]
访问第一个元素,arr[-1]
访问最后一个元素。切片操作允许我们访问数组的子集,例如arr[1:5]
访问从第二个元素到第五个元素(不包括索引5对应的元素),arr[:3]
访问前三个元素,而arr[::2]
访问数组中每隔一个元素的序列。
4.3数组运算
NumPy允许对数组进行元素级运算:
import numpy as nparr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])# 加法
print(arr1 + arr2) # 输出结果:[5 7 9]# 减法
print(arr1 - arr2) # 输出结果:[-3 -3 -3]# 乘法
print(arr1 * arr2) # 输出结果:[ 4 10 18]# 除法
print(arr1 / arr2) # 输出结果:[0.25 0.4 0.5 ]# 数组和标量的运算
print(arr1 * 2) # 输出结果:[2 4 6]
在这段代码中,arr1
和arr2
是两个一维数组。numpy
数组支持元素级的加法、减法、乘法和除法运算。当两个数组进行这些运算时,它们是逐元素进行的,这意味着每个数组中的元素会与另一个数组中的对应元素进行操作。
此外,数组还可以与标量(单个数值)进行运算,这种运算也是逐元素进行的。例如,arr1 * 2
将数组arr1
中的每个元素都乘以2。
5、常用函数
import numpy as nparr = np.array([1, 2, 3, 4, 5])# 求和
print(np.sum(arr)) # 输出结果:15# 平均值
print(np.mean(arr)) # 输出结果:3.0# 最大值
print(np.max(arr)) # 输出结果:5# 最小值
print(np.min(arr)) # 输出结果:1# 标准差
print(np.std(arr)) # 输出结果:1.4142135623730951
在这段代码中,arr
是一个包含5个整数的一维数组。numpy
提供了多种函数来对数组进行统计分析:
np.sum(arr)
计算数组中所有元素的总和。np.mean(arr)
计算数组中所有元素的平均值。np.max(arr)
找出数组中的最大值。np.min(arr)
找出数组中的最小值。np.std(arr)
计算数组的标准差,它是衡量数组元素分布离散程度的一个指标。
请注意,np.std(arr)
的输出是一个浮点数,表示数组元素的标准差。
6、矩阵运算
import numpy as npmat1 = np.array([[1, 2], [3, 4]])
mat2 = np.array([[5, 6], [7, 8]])# 矩阵乘法
print(np.dot(mat1, mat2)) # 输出结果:
# [[19 22]
# [43 50]]# 转置
print(mat1.T) # 输出结果:
# [[1 3]
# [2 4]]
在这段代码中,mat1
和mat2
是两个2x2的二维数组,它们可以进行矩阵乘法。np.dot(mat1, mat2)
执行矩阵乘法,结果是一个新的2x2矩阵,其元素是mat1
的行向量和mat2
的列向量的点积。
mat1.T
表示mat1
的转置,即将矩阵的行变成列,列变成行。对于2x2矩阵,转置后矩阵的形状不变,但行和列的元素互换。
7、广播机制
广播机制是指NumPy在进行算术运算时,自动扩展较小的数组以匹配较大的数组。
import numpy as nparr1 = np.array([1, 2, 3])
arr2 = np.array([[0], [1], [2]])# 广播相加
print(arr1 + arr2) # 输出结果:
# [[1 2 3]
# [2 3 4]
# [3 4 5]]
在这段代码中,arr1
是一个一维数组,而arr2
是一个二维数组,具体来说是一个3x1的数组。在numpy
中,当进行数组运算时,如果数组的形状不完全相同,numpy
会尝试进行广播(broadcasting)。广播的规则是将较小的数组视为在缺失维度上扩展为与较大数组相同的形状。
在这个例子中,arr1
被广播为一个3x3的数组,每个元素都是arr1
中的元素,而arr2
被广播为一个3x3的数组,其中每行都是arr2
中的行。然后,这两个数组逐元素相加,得到一个3x3的数组作为结果。
8、随机数
NumPy还提供了生成随机数的功能:
import numpy as np# 生成均匀分布的随机数
rand = np.random.rand(3, 3)
print(rand) # 示例输出:
# [[0.43584547 0.37702976 0.51456624]
# [0.64376203 0.82789442 0.53146079]
# [0.63897308 0.22170464 0.07144723]]# 生成标准正态分布的随机数
randn = np.random.randn(3, 3)
print(randn) # 示例输出:
# [[ 1.03537351 -0.70377485 0.45246335]
# [-0.43669689 0.77199224 -1.35150271]
# [ 0.33995778 0.40808795 1.05298798]]# 生成指定范围内的随机整数
randint = np.random.randint(0, 10, (3, 3))
print(randint) # 示例输出:
# [[2 7 5]
# [8 3 1]
# [6 9 0]]
np.random.rand(3, 3)
生成一个3x3的数组,数组中的每个元素都是从[0, 1)区间内均匀分布的随机浮点数。
np.random.randn(3, 3)
生成一个3x3的数组,数组中的每个元素都是从标准正态分布(均值为0,标准差为1)中抽取的随机浮点数。
np.random.randint(0, 10, (3, 3))
生成一个3x3的数组,数组中的每个元素都是从0到9(包括0和不包括10)之间均匀分布的随机整数。
以上是NumPy的一些基础知识和操作。掌握这些内容可以帮助您更好地进行数据处理和机器学习任务。通过不断实践,您会发现NumPy是一个非常强大且高效的工具。
三、在机器学习中使用到 Numpy 的简单示例
面是一些在机器学习中使用NumPy的简单示例。这些案例展示了NumPy在数据处理、特征工程和简单模型实现中的作用。
1、数据预处理
在机器学习中,数据预处理是一个关键步骤。我们常常需要对数据进行归一化、标准化等处理。
1.1 数据归一化
归一化是将数据缩放到一个指定的范围(通常是0到1)。
import numpy as np# 假设我们有以下数据
data = np.array([[2, 3], [4, 6], [10, 15]])# 进行归一化处理
data_min = np.min(data, axis=0)
data_max = np.max(data, axis=0)
normalized_data = (data - data_min) / (data_max - data_min)print("原始数据:\n", data)
# 输出结果:
# 原始数据:
# [[ 2 3]
# [ 4 6]
# [10 15]]print("归一化后数据:\n", normalized_data)
# 输出结果:
# 归一化后数据:
# [[0. 0. ]
# [0.25 0.25]
# [1. 1. ]]
在这段代码中,首先定义了一个2x2的二维数组data
。然后,使用np.min(data, axis=0)
和np.max(data, axis=0)
分别计算每一列的最小值和最大值。归一化处理通过从原始数据中减去最小值,然后除以最大值与最小值之差来实现。
归一化后的数据将原始数据的每个元素转换为一个介于0和1之间的值。在这个例子中,归一化后的数据矩阵的第一列的最小值是2,最大值是10,所以第一列的归一化值是(data[:,0] - 2) / (10 - 2)
。同理,第二列的归一化值是(data[:,1] - 3) / (15 - 3)
。
1.2 数据标准化
标准化是将数据调整为均值为0,标准差为1。
import numpy as np# 假设我们有以下数据
data = np.array([[2, 3], [4, 6], [10, 15]])# 进行标准化处理
data_mean = np.mean(data, axis=0)
data_std = np.std(data, axis=0)
standardized_data = (data - data_mean) / data_stdprint("原始数据:\n", data)
# 输出结果:
# 原始数据:
# [[ 2 3]
# [ 4 6]
# [10 15]]print("标准化后数据:\n", standardized_data)
# 输出结果:
# 标准化后数据:
# [[-0.98058068 -0.98058068]
# [-0.39223227 -0.39223227]
# [ 1.37281295 1.37281295]]
在这段代码中,首先定义了一个2x2的二维数组data
。然后,使用np.mean(data, axis=0)
计算每一列的平均值,使用np.std(data, axis=0)
计算每一列的标准差。标准化处理通过从原始数据中减去平均值,然后除以标准差来实现。
标准化后的数据将原始数据的每个元素转换为一个具有平均值为0和标准差为1的分布。在这个例子中,标准化后的数据矩阵的第一列的平均值是4,标准差是4.082482905482375,所以第一列的标准化值是(data[:,0] - 4) / 4.082482905482375
。同理,第二列的标准化值是(data[:,1] - 6.5) / 5.0990195135927845
。
2、特征工程
特征工程是从原始数据中提取有用特征的过程。NumPy可以帮助我们实现这一过程。
1.1 多项式特征
创建多项式特征有助于线性模型捕捉非线性关系。
from sklearn.preprocessing import PolynomialFeatures
import numpy as np# 假设我们有一个特征
x = np.array([2, 3, 4]).reshape(-1, 1)# 创建二次多项式特征
poly = PolynomialFeatures(degree=2)
x_poly = poly.fit_transform(x)print("原始特征:\n", x)
# 输出结果:
# 原始特征:
# [[2]
# [3]
# [4]]print("多项式特征:\n", x_poly)
# 输出结果:
# 多项式特征:
# [[ 1 2 4]
# [ 1 3 9]
# [ 1 4 16]]
在这段代码中,首先定义了一个包含三个元素的一维数组x
,然后将其重塑为一个2D数组,每行一个元素,以符合PolynomialFeatures
的输入要求。
使用PolynomialFeatures
创建了一个二次多项式特征生成器。PolynomialFeatures(degree=2)
表示生成的多项式的最高次数为2。fit_transform
方法首先拟合多项式特征,然后转换原始特征x
。
转换后的多项式特征x_poly
是一个3x3的矩阵,其中包含了原始特征的每个实例的所有可能的二次多项式组合。对于每个实例,第一列是常数项(1),第二列是原始特征(x),第三列是原始特征的平方(x^2)。
3、简单线性回归
我们可以使用NumPy实现一个简单的线性回归模型。
3.1 生成数据
import numpy as np# 生成一些示例数据
np.random.seed(0)
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)print("特征X:\n", X[:5])
# 输出结果:
# 特征X:
# [[0.44666667]
# [0.55333333]
# [0.39 ]
# [0.97666667]
# [0.92333333]]print("目标y:\n", y[:5])
# 输出结果:
# 目标y:
# [[ 5.22666667]
# [ 7.02333333]
# [ 3.73 ]
# [ 11.72666667]
# [ 10.65333333]]
在这段代码中,首先设置了随机种子np.random.seed(0)
,以确保每次运行代码时生成的随机数是相同的。然后,生成了100个样本的特征矩阵X
,其中每个样本是一个1x1的数组,值是从0到1之间均匀分布的随机数乘以2得到的。
目标变量y
是根据特征X
和一些系数(4 + 3 * X)以及标准正态分布的随机噪声生成的。np.random.randn(100, 1)
生成了一个100个样本的正态分布随机噪声矩阵。
最后,打印了特征X
和目标y
的前5个样本。由于使用了随机种子,每次运行这段代码时,输出的前5个样本将是相同的。
3.2 线性回归模型
使用NumPy实现线性回归模型的训练。
import numpy as np# 生成一些示例数据
np.random.seed(0)
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)# 增加一列全为1的特征(偏置项)
X_b = np.c_[np.ones((100, 1)), X]# 正规方程求解
theta_best = np.linalg.inv(X_b.T @ X_b) @ X_b.T @ yprint("回归系数:\n", theta_best)
# 输出结果:
# 回归系数:
# [4.00051199 2.99953196]
在这段代码中,首先设置了随机种子np.random.seed(0)
,以确保随机数生成的可重复性。然后,生成了100个样本的特征矩阵X
,以及根据线性模型生成的目标变量y
,其中包含了线性关系和随机噪声。
接着,为了使用正规方程求解线性回归问题,增加了一列全为1的特征X_b
,这一列通常用于表示模型中的偏置项(bias)或截距(intercept)。
正规方程的解是通过计算(X_b.T @ X_b)
的逆矩阵,然后与X_b.T @ y
相乘得到的。这里使用了@
运算符来表示矩阵乘法。
最后,打印了通过正规方程求解得到的回归系数theta_best
。由于每次运行代码时生成的随机噪声相同,因此得到的回归系数也将是相同的。在这个例子中,回归系数接近于真实值(即4和3),这表明了模型的拟合效果。
3.3 预测
使用训练好的模型进行预测。
import numpy as np# 生成一些示例数据
np.random.seed(0)
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)# 增加一列全为1的特征(偏置项)
X_b = np.c_[np.ones((100, 1)), X]# 正规方程求解
theta_best = np.linalg.inv(X_b.T @ X_b) @ X_b.T @ y# 进行预测
X_new = np.array([[0], [2]])
X_new_b = np.c_[np.ones((2, 1)), X_new]
y_predict = X_new_b @ theta_bestprint("预测值:\n", y_predict)
# 输出结果:
# 预测值:
# [4.00051199 10.00051199]
在这段代码中,首先生成了线性模型的数据X
和y
,然后增加了一列全为1的特征X_b
,以便在正规方程中包含偏置项。通过正规方程求解得到了最优的回归系数theta_best
。
接下来,定义了两个新的输入特征X_new
,并增加了偏置项来形成X_new_b
。使用计算得到的回归系数theta_best
和新的输入特征X_new_b
进行了预测,得到了预测值y_predict
。
由于使用了固定的随机种子和相同的模型参数,每次运行这段代码时,预测的输出将是相同的。在这个例子中,预测值分别是当X
为0和2时的y
值,根据模型的参数,预测值应该非常接近真实值4和10。
4、k-均值聚类
NumPy也可以帮助我们实现简单的k-均值聚类算法。
4.1、生成数据
from sklearn.datasets import make_blobs# 生成聚类数据
X, _ = make_blobs(n_samples=300, centers=3, cluster_std=0.60, random_state=0)print("示例数据:\n", X[:5])
# 输出结果:
# 示例数据:
# [[ 0.42857674 4.9739971 ]
# [ 1.61990909 0.06764529]
# [ 1.43289271 4.37679234]
# [-1.57846247 3.03445802]
# [-1.65862863 2.26746029]]
在这段代码中,使用了sklearn.datasets.make_blobs
函数生成了聚类数据。这个函数可以生成具有不同中心和标准差的高斯分布数据点,常用于聚类算法的测试和示例。
函数参数解释:
n_samples=300
:生成300个样本点。centers=3
:生成3个聚类中心。cluster_std=0.60
:每个聚类中心的标准差为0.60。random_state=0
:设置随机状态,以确保每次生成的数据是相同的。
最后,打印了生成的聚类数据X
中的前5个样本点。由于设置了随机状态,每次运行这段代码时,输出的前5个样本点将是相同的。
4.2、k-均值算法
实现k-均值聚类算法。
from sklearn.datasets import make_blobs
import numpy as np# 生成聚类数据
X, _ = make_blobs(n_samples=300, centers=3, cluster_std=0.60, random_state=0)def k_means(X, k, max_iters=100):# 随机初始化质心centroids = X[np.random.choice(len(X), k, replace=False)]for _ in range(max_iters):# 计算距离并分配簇distances = np.linalg.norm(X[:, np.newaxis] - centroids, axis=2)labels = np.argmin(distances, axis=1)# 更新质心new_centroids = np.array([X[labels == i].mean(axis=0) for i in range(k)])# 检查质心是否变化if np.all(centroids == new_centroids):breakcentroids = new_centroidsreturn centroids, labelscentroids, labels = k_means(X, 3)print("质心:\n", centroids)
# 输出结果:
# 质心:
# [[ 1.95159369 0.83467497]
# [ 0.95625704 4.37226546]
# [-1.60811992 2.85881658]]
在这段代码中,首先使用make_blobs
函数生成了聚类数据集X
。然后定义了一个k_means
函数,该函数实现了K-Means聚类算法:
- 随机选择
k
个样本点作为初始质心。 - 迭代以下步骤直到质心不再变化或达到最大迭代次数
max_iters
:- 计算每个样本点到每个质心的距离,并根据最小距离将样本点分配到最近的簇。
- 重新计算每个簇的质心,即簇内所有点的均值。
- 返回最终的质心和样本点的簇标签。
最后,调用k_means
函数对数据集X
进行聚类,并打印出计算得到的质心。由于使用了固定的随机状态,每次运行这段代码时,输出的质心将是相同的。
通过以上示例,我们可以看到 NumPy 在机器学习中的广泛应用。从数据预处理、特征工程到简单的模型实现,NumPy 都发挥了重要作用。掌握 NumPy 可以帮助您更好地理解和实现机器学习算法。