小白从零开始勇闯人工智能:机器学习初级篇(Numpy库下)
在上一章中我们Numpy库中的数组元素有了基本的认识,博主将和大家在这一章里学习如何去操作修改这些数组元素。
一、 数组的组合:数据的"拼接艺术"
1、水平组合
np.hstack()或 np.concatenate(axis=1)用于将多个数组沿水平方向(按列)组合。所有数组在垂直方向上要形状相同。例如,两个 2x2 数组水平组合后变为 2x4 数组。hstack() 可同时合并多个数组,而 concatenate() 需指定 axis=1 实现相同效果。
import numpy as np
# 创建两个数组
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
print(f"数组1:\n{arr1}")
print(f"数组2:\n{arr2}")
# 水平组合(按列合并)
hstack1 = np.hstack((arr1, arr2))
print(f"\n水平组合1:\n{hstack1}")
# 使用concatenate实现水平组合
hstack2 = np.concatenate((arr1, arr2), axis=1) # axis=1表示水平方向
print(f"\n使用concatenate水平组合:\n{hstack2}")

2、垂直组合
np.vstack()或np.concatenate(axis=0)用于将多个数组沿垂直方向堆叠。要求所有数组在水平方向上形状相同。例如,两个 2x2 数组垂直堆叠后变为 4x2 数组。对于一维数组,vstack() 会将其视为单行数据,堆叠后形成二维数组。
import numpy as np
# 创建两个数组
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
print(f"数组1:\n{arr1}")
print(f"数组2:\n{arr2}")
# 垂直组合
vstack1 = np.vstack((arr1, arr2))
print(f"\n垂直组合1:\n{vstack1}")
# 使用concatenate实现垂直组合
vstack2 = np.concatenate((arr1, arr2), axis=0) # axis=0表示垂直方向
print(f"\n使用concatenate垂直组合:\n{vstack2}")

二、NumPy数组元素的切割:数据的"分割手术"
1、水平切割(按列分割)
np.hsplit()用于将数组沿水平方向(按列)分割为多个子数组。分割份数必须能被总列数整除。例如,一个 4x4 的数组使用 np.hsplit(arr, 2) 会被分割为两个 4x2 的子数组。
import numpy as np
# 创建4x4数组
arr = np.arange(16).reshape(4, 4)
print(f"原始数组:\n{arr}")
# 水平切割成2部分
hsplit1 = np.hsplit(arr, 2)
print(f"\n水平切割成2部分:")
for i, part in enumerate(hsplit1):
print(f"第{i+1}部分:\n{part}")
# 使用split函数
print(f"\n使用split水平切割:")
split_h = np.split(arr, 2, axis=1) # axis=1水平
for i, part in enumerate(split_h):
print(f"第{i+1}部分:\n{part}")

2、垂直切割(按行分割)
np.vsplit()用于将数组沿垂直方向(按行)分割为多个子数组,要求分割份数能被总行数整除。例如,一个 4x4 的数组通过 np.vsplit(arr, 2) 会被分割为两个 2x4 的子数组。
# 垂直切割成2部分
vsplit1 = np.vsplit(arr, 2)
print(f"\n垂直切割成2部分:")
for i, part in enumerate(vsplit1):
print(f"第{i+1}部分:\n{part}")
# 使用split函数
print(f"\n使用split垂直切割:")
split_v = np.split(arr, 2, axis=0) # axis=0垂直
for i, part in enumerate(split_v):
print(f"第{i+1}部分:\n{part}")

3、不等份切割
np.array_split()允许将数组分割成指定数量的不等份子数组。当总行数或列数不能被份数整除时,它会自动调整各子数组的大小。例如,对一个 5x5 数组水平切割成 3 份(axis=1),由于 5 列无法被 3 整除,子数组的列数分配为 2、2、1。
import numpy as np
# 创建5x5数组
arr = np.arange(25).reshape(5, 5)
print(f"5x5数组:\n{arr}")
# 水平方向切割成3份(不等份)
split_uneven_h = np.array_split(arr, 3, axis=1)
print(f"\n水平不等份切割(3份):")
for i, part in enumerate(split_uneven_h):
print(f"第{i+1}部分(形状:{part.shape}):\n{part}")

三、数组的算术运算:数据的"数学游戏"
1、基本算术运算
NumPy的算术运算基于向量化实现,直接对整个数组执行逐元素操作。这些运算包括对应元素的加法(+)、减法(-)、乘法(*)、除法(/)、取余(%)、取整除(//)和幂运算(**)。需要注意的是,这里的乘法是元素对应相乘,而非矩阵乘法。
import numpy as np
# 创建两个数组
arr1 = np.array([1, 2, 3, 4])
arr2 = np.array([5, 6, 7, 8])
print(f"数组1:{arr1}")
print(f"数组2:{arr2}")
# 加法(对应元素相加)
print(f"\n加法:{arr1} + {arr2} = {arr1 + arr2}")
# 减法
print(f"减法:{arr1} - {arr2} = {arr1 - arr2}")
# 乘法
print(f"乘法:{arr1} * {arr2} = {arr1 * arr2}")
# 除法
print(f"除法:{arr1} / {arr2} = {arr1 / arr2}")
# 取余
print(f"取余:{arr2} % {arr1} = {arr2 % arr1}")
# 取整除法
print(f"取整:{arr2} // {arr1} = {arr2 // arr1}")
# 幂运算
print(f"幂运算:{arr1}² = {arr1 ** 2}")

2、数组与标量的运算
NumPy支持数组与标量(单个数值)之间直接运算,当一个数组与一个标量进行运算时,该标量会自动到数组的每个元素上,执行逐步元素操作。例如,数组 [1, 2, 3, 4] 与标量 10 相加,结果为 [11, 12, 13, 14];与标量 2 相乘,结果为 [2, 4, 6, 8]。
import numpy as np
arr = np.array([1, 2, 3, 4])
print(f"\n数组:{arr}")
print(f"数组 + 10 = {arr + 10}")
print(f"数组 × 2 = {arr * 2}")
print(f"数组 / 2 = {arr / 2}")
print(f"数组 ^ 3 = {arr ** 3}")

3、比较运算
NumPy的比较运算在数组间逐个元素进行,并返回一个布尔值数组。例如 a[a > 3] 会提取a中所有大于3的值。多个条件可通过逻辑运算符(如 & 表示“且”,| 表示“或”)组合,如a[(a > 2) & (b > 2)]。
import numpy as np
# 创建两个数组
a = np.array([1, 2, 3, 4, 5])
b = np.array([5, 4, 3, 2, 1])
print(f"a = {a}")
print(f"b = {b}")
print(f"\na > b:{a > b}")
print(f"a == b:{a == b}")
print(f"a <= 3:{a <= 3}")
# 使用比较结果进行筛选
print(f"\na中大于3的元素:{a[a > 3]}")
print(f"a和b对应位置都大于2的元素:{a[(a > 2) & (b > 2)]}")

四、数组的深拷贝与浅拷贝:数据的"复制魔法"
1、浅拷贝
NumPy中的浅拷贝是指多个数组变量共享同一块内存数据,修改其中一个会影响其他。最直接的浅拷贝是直接赋值,这实际上只是创建了一个新的变量名指向同一数组对象,因此两个变量的内存地址相同。
import numpy as np
# 创建原始数组
original = np.array([1, 2, 3, 4, 5])
print(f"原始数组:{original}")
# 浅拷贝(引用同一个内存地址)
shallow_copy = original
print(f"\n浅拷贝后:")
print(f"原始数组id:{id(original)}")
print(f"浅拷贝id:{id(shallow_copy)}")
# 修改浅拷贝会影响原始数组
shallow_copy[0] = 100
print(f"\n修改浅拷贝后:")
print(f"原始数组:{original}")
print(f"浅拷贝:{shallow_copy}")

2、深拷贝
copy()方法用于创建数组的深拷贝,即生成一个与原始数组数据完全相同但内存独立的新数组。深拷贝后,两个数组的ID不同,修改其中一个不会影响另一个。
import numpy as np
# 创建原始数组
original = np.array([1, 2, 3, 4, 5])
print(f"原始数组:{original}")
# 深拷贝(创建新数组)
deep_copy = original.copy()
print(f"\n深拷贝后:")
print(f"原始数组id:{id(original)}")
print(f"深拷贝id:{id(deep_copy)}")
# 修改深拷贝不会影响原始数组
deep_copy[0] = 999
print(f"\n修改深拷贝后:")
print(f"原始数组:{original}") # 保持不变
print(f"深拷贝:{deep_copy}")

五、NumPy内的随机模块:数据的"随机生成器"
1、随机整数
np.random.randint()用于生成指定范围内的随机整数数组。通过设置随机种子可确保结果可复现。该函数包含下限、不包含上限和输出形状参数。
import numpy as np
# 设置随机种子(确保结果可重现)
np.random.seed(32)
# 生成0-9之间的随机整数
single_random = np.random.randint(0, 10)
print(f"单个随机整数(0-9):{single_random}")
# 生成10个0-9的随机整数
ten_randoms = np.random.randint(0, 10, size=10)
print(f"10个随机整数:{ten_randoms}")
# 生成3x3的随机整数矩阵
matrix_3x3 = np.random.randint(0, 10, size=(3, 3))
print(f"3x3随机矩阵:\n{matrix_3x3}")
# 生成5个1-100的随机整数
rand_1_100 = np.random.randint(1, 101, size=5)
print(f"5个1-100的随机数:{rand_1_100}")

2、均匀分布随机数
NumPy的random模块提供了生成多种分布随机数的功能。生成均匀分布的随机浮点数主要有两种方式:np.random.rand(d0, d1, ...) 直接生成 [0, 1) 区间内均匀分布的浮点数,参数指定各维度大小。np.random.uniform(low, high, size) 可在任意指定范围 [low, high) 内生成均匀分布的随机数。
import numpy as np
# 生成0-1之间的随机浮点数
single_float = np.random.rand()
print(f"单个0-1随机数:{single_float:.4f}")
# 生成5个0-1的随机数
five_floats = np.random.rand(5)
print(f"5个0-1随机数:{[f'{x:.4f}' for x in five_floats]}")
# 生成3x3的随机矩阵
random_matrix = np.random.rand(3, 3)
print(f"\n3x3随机矩阵:\n{random_matrix}")
# 生成指定范围的均匀分布随机数
uniform_nums = np.random.uniform(10, 20, size=5)
print(f"\n10-20均匀分布:{[f'{x:.2f}' for x in uniform_nums]}")

3、正态分布随机数
np.random.normal()用于生成符合正态分布的随机数。关键参数为 loc(均值,分布的中心点)、scale(标准差,分布的离散程度)和 size(输出形状)。
import numpy as np
# 标准正态分布(均值0,标准差1)
standard_normal = np.random.normal(size=5)
print(f"标准正态分布:{[f'{x:.4f}' for x in standard_normal]}")
# 自定义正态分布
# normal(loc=均值, scale=标准差, size=形状)
custom_normal = np.random.normal(loc=100, scale=15, size=5)
print(f"均值100,标准差15:{[f'{x:.2f}' for x in custom_normal]}")
# 生成正态分布矩阵
normal_matrix = np.random.normal(loc=0, scale=1, size=(3, 3))
print(f"\n3x3正态分布矩阵:\n{normal_matrix}")

六、NumPy内一些函数的使用:数据的"统计工具箱"
1、基本统计函数
NumPy提供了全面的统计函数,用于对数组数据进行数学分析。核心函数包括:sum() 计算总和,mean() 求平均值,std() 和 var() 分别计算标准差与方差(用于衡量数据离散程度),min() 和 max() 找出极值,median() 确定中位数,以及 percentile() 计算任意百分位数(如四分位数)。
import numpy as np
# 创建
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(f"测试数组:{arr}")
# 求和
print(f"总和:{np.sum(arr)}")
print(f"总和(方法):{arr.sum()}")
# 均值
print(f"均值:{np.mean(arr):.2f}")
print(f"均值(方法):{arr.mean():.2f}")
# 标准差
print(f"标准差:{np.std(arr):.2f}")
# 方差
print(f"方差:{np.var(arr):.2f}")
# 最大值和最小值
print(f"最大值:{np.max(arr)}")
print(f"最小值:{np.min(arr)}")
# 中位数
print(f"中位数:{np.median(arr)}")
# 百分位数
print(f"25%分位数:{np.percentile(arr, 25)}")
print(f"75%分位数:{np.percentile(arr, 75)}")

七、矩阵的运算:线性代数的"核心武器"
1、基本矩阵运算
这些矩阵运算遵循线性代数规则:前者的列数必须等于后者的行数。
import numpy as np
# 创建两个矩阵
A = np.array([[1, 2],
[3, 4]])
B = np.array([[5, 6],
[7, 8]])
print(f"矩阵A:\n{A}")
print(f"\n矩阵B:\n{B}")
# 矩阵加法(对应元素相加)
print(f"A + B:\n{A + B}")
# 矩阵减法
print(f"\nA - B:\n{A - B}")
# 矩阵除法
print(f"\nA / B:\n{A / B}")

2、矩阵乘法(点积)
要实现NumPy中真正的矩阵乘法(点积),需要使用np.dot() 函数:np.dot(A, B)。
import numpy as np
# 创建两个矩阵
A = np.array([[1, 2],
[3, 4]])
B = np.array([[5, 6],
[7, 8]])
#使用dot函数
C_dot = np.dot(A, B)
print(f"使用dot函数:\n{C_dot}")

3、矩阵的逆
NumPy的np.linalg.inv()函数用于计算方阵(行数和列数相等的矩阵)的逆矩阵。只有行列式不为零的方阵才存在逆矩阵。
import numpy as np
# 只有方阵才有可能有逆矩阵
A = np.array([[4, 7],
[2, 6]])
a = np.linalg.inv(A)
print(f"矩阵A:\n{A}")
print(f"\nA的逆矩阵:\n{a}")

八、读取文件:数据的"输入输出"
1、保存文件
np.savetxt() 函数用于将 NumPy 数组以文本格式保存到文件中。默认情况下,数据会以科学计数法保存,但可以通过 fmt 参数指定格式,通过 delimiter 参数指定分隔符。
import numpy as np
# 创建文件
data_to_save = np.array([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0],
[7.0, 8.0, 9.0]])
# 保存到文件
np.savetxt('data.txt', data_to_save, fmt='%.2f')

2、读取文件
np.loadtxt() 函数用于从文本文件加载数据到 NumPy 数组,要求文件每行具有相同数量的值。可以通过 delimiter 参数指定分隔符(如制表符 \t、逗号 , 等)。
import numpy as np
loaded_data = np.loadtxt('data.txt')
print(f"从文件读取的数据:\n{loaded_data}")
print(f"数据类型:{loaded_data.dtype}")
print(f"数据形状:{loaded_data.shape}")

到这里我们就基本完成了对numpy库的学习,为接下来的机器学习打下了坚实的基础,在下一章博主将和大家一起学习机器学习中另外两个库:matplotlib和Pandas库。
更多推荐
所有评论(0)