已经决定要参加今年的数模比赛了
time table:
2月 -> 美赛
5月 -> 华中杯
9月 -> 国赛
要用一年的时间从小白到拿个果酱的水平. 本post用来记录一些python数学建模的笔记, 之后可能会针对matlab单独再开一个post, 谨以此作为记录.
Tips
- 在pytorch中, 以下划线结尾的函数代表在原位操作, 不带下划线的函数操作会返回一个新的对象但是不会作用在原对象上
Numpy
quick start
部分基础numpy已经在本站post中做过介绍: 动手学深度学习
Index & Slice
flat iterator:
flat返回一个遍历全体元素的迭代器
for element in b.flat:
print(element)
general slice:
a = np.array([2, 4, 8, 20, 16, 30])
a[[2, 3, 5]] # output: [8 20 30] 方括号嵌套代表指定位置切片
b[[2, 3], 1:4] # output: 输出第3, 4行, 第2, 3, 4列的元素
boolean index:
在方括号中填写bool表达式可以返回筛选出符合条件元素组成的切片
from numpy inport array, nan, isnan
a = array([[1, nan, 2], [4, nan, 3]])
b = a[not isnan(a)] # 筛选出不为nan的切片(但是维度丢失, 默认一维)
花式索引:
即方括号嵌套: b[[2, 3], 1:4] # output: 输出第3, 4行, 第2, 3, 4列的元素
数组的修改:
修改元素 维度扩张或缩小
y = np.delete(x, 2, axis=0) # 删除第三行
t2 = np.append(x, [[9], [10], [11]], axis=1) # 增加一列
步长:
在NumPy中,:: 是切片语法中的步长(stride)部分,用于指定从一个序列中提取元素的间隔。NumPy的切片语法通常采用以下形式:
start:stop:step
start:起始索引,表示切片的开始位置。
stop:结束索引,表示切片的结束位置(不包含该位置的元素)。
step:步长,表示从起始索引到结束索引的间隔。
数组的变形:
Shape manipulation
a.ravel() # returns the array, flattened
a.reshape(6, 2) # returns the array with a modified shape keeping the natural order
a.T # returns the array, transposed
a.resize((3, -1))
# 列组合,构造分块数组
np.c_(a, b)
# 行组合
np.r_(a, b)
# 水平展开数组
a.ravel() # 返回的是a的视图
a.flatten() # 返回真实的数组,需要分配新的内存
# 数组的组合
np.hstack((a, b))
np.vstack((a, b))
np.concatenate((a, b), axis=1) # 等同于hstack
reshape
和 ravel
的操作遵循C-style, 这意味着index中最右端的索引对应的位置是变化最快的, 如a[0, 0]的下一个是a[0, 1].
resize
直接修改array本身 而 reshape
会返回一个修改过的array, 即仅返回视图.
文件存取
text file
savetxt()
和loadtxt()
只能够存取1, 2维数组- genfromtxt
binary file
- tofile() 和 fromfile()
- load(), save(), savez()存取numpy专用二进制格式文件
如果西药将多个数组保存到一个文件中, 可以使用savez().a = np.arange(6).reshape(2, 3) np.save('data.npy', a) b = load('data.npy') np.savez('data.npz', c, d) e = np.load('data.npz') f1 = e['arr_0'] # get c
Tricks
打印完整ndarray:
np.set_printoptions(threshold=sys.maxsize) # sys module should be imported
A @ b # equals to A.dot(B)
Function tips
permute & view & transpose:
两者都是针对一个tensor的维度与形状上进行操作, 但是permute针对的是维度之间的交换, 为view针对的是形状的调整.
可以理解为在permute函数中, tensor排列不变, 但是tensor的坐标系发生了变换(包裹元素的方括号发生了变换), 而view是直接调整维度, 保证顺序不变的原则.
permute 和 view 在作用上有较大的区别,于此相比, transpose和permute的差异就显得很小, 两者都是用来调整维度顺序的函数, 不同的是: transpose
不会调整ndarray在内存中的存储方式, permute
会对内存中的存储顺序进行调整, 从而提高计算效率.
arange & linspace:
np.arange(begin, end, step) # arange指定间隔
np.linspace(begin, end, num) # linspace指定数量
Unary operations:
a = rg.random((2, 3))
a
array([[0.82770259, 0.40919914, 0.54959369],
[0.02755911, 0.75351311, 0.53814331]])
a.sum()
3.1057109529998157
a.min()
0.027559113243068367
a.max()
0.8277025938204418
# you can also specify axis
b = np.arange(12).reshape(3, 4)
b
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
b.sum(axis=0) # sum of each column
array([12, 15, 18, 21])
Universal functions:
包括一些常用函数,作用域ndarray中的每一个元素
np.exp(B)
# array([1. , 2.71828183, 7.3890561 ])
np.sqrt(B)
# array([0. , 1. , 1.41421356])
C = np.array([2., -1., 4.])
np.add(B, C)
# array([2., 0., 6.])
Sympy
通过Sympy可以实现符号运算
from sympy import *
x = symbols('x')
y, z = symbols('y x')
m0, m1, m2, m3 = symbols('m0:4') # 生成符号序列
x = sin(1) # 注意这里使用的是sympy中的函数
print('x=', x.n(16)) # 打印小数点后16位
print(f'{pi}, {pi.evalf(3)}') # 打印小数点后3位
expr1 = y*sin(y**2)
expr2 = y**@ + sin(y) * cos(y) + sin(z)
print(expr1.subs(y, 5))
print(expr2.subs({y:2, z:3}).n())
sympy 处理有理数
from sympy import *
速速更新,别逼我求你
我错了哥这就更😭