【joyful pandas 01】基础知识03

一些基础练习题

附上前面的学习笔记链接

https://blog.csdn.net/weixin_45389860/article/details/111163226

https://blog.csdn.net/weixin_45389860/article/details/111241656

1.利用列表推导式矩阵乘法

M1 = np.random.rand(2,3)
M2 = np.random.rand(3,4)
res = np.empty((M1.shape[0],M2.shape[1]))
for i in range(M1.shape[0]):
    for j in range(M2.shape[1]):
        item = 0
        for k in range(M1.shape[1]):
            item += M1[i][k] * M2[k][j]
        res[i][j] = item
((M1@M2 - res) < 1e-15).all() # 排除数值误差

其三重循环表达式应该如上图所示,将以上的表达式转化成列表推导式的形式:

注意一下是我的错误示例

M1 = np.random.rand(2,3)
M2 = np.random.rand(3,4)
res = [sum([M1[i][k]*M2[k][j]]) for i in range(M1.shape[0]) for j in range(M2.shape[1]) for k in range(M1.shape[1])]
# 检验是否通过

这里遇到一个问题,成功生成了这段list,但是后面想一下,list可以和ndarray数据进行运算嘛?

以上是一种错误的实例,由于各个循环之间没有嵌套括号分开来导致其没有实现在列表推导式中的循环嵌套:一下是纠正后的实例:

np.random.seed(0)
M1 = np.random.rand(2,3)
M2 = np.random.rand(3,4)
res = [[sum([M1[i][k] * M2[k][j] for k in range(M1.shape[1])]) for j in range(M2.shape[1])] for i in range(M1.shape[0])]
((M1@M2 - res) < 1e-15).all()
res
True

2.更新矩阵

设矩阵 A m × n A_{m×n} Am×n ,现在对 A A A 中的每一个元素进行更新生成矩阵 B B B ,更新方法是 B i j = A i j ∑ k = 1 n 1 A i k B_{ij}=A_{ij}\sum_{k=1}^n\frac{1}{A_{ik}} Bij=Aijk=1nAik1 ,例如下面的矩阵为 A A A ,则 B 2 , 2 = 5 × ( 1 4 + 1 5 + 1 6 ) = 37 12 B_{2,2}=5\times(\frac{1}{4}+\frac{1}{5}+\frac{1}{6})=\frac{37}{12} B2,2=5×(41+51+61)=1237 ,请利用 Numpy 高效实现。
latex公式乱码,mark一下

先让憨憨来曲解曲解题意:

挂一张大神的理解
来自datawhale 黄元帅

按照公式 B i j = A i j ∑ k = 1 n 1 A i k B_{ij}=A_{ij}\sum_{k=1}^n\frac{1}{A_{ik}} Bij=Aijk=1nAik1,先是对A数组按照行进行求和,然后再与相应的数值进行计算

A = np.arange(1,10).reshape(3,-1)
B = A*(1/A).sum(axis=1).reshape(-1,1)
B
array([[1.83333333, 3.66666667, 5.5       ],
       [2.46666667, 3.08333333, 3.7       ],
       [2.65277778, 3.03174603, 3.41071429]])

mark 一下自己烦的错误,一开始没有理解的内容是,这里的整个表达公式,当然应该是一个完整的公式应该被优先表达,这里的(1/A).sum(axis=1).reshape(-1,1)实际上是一个整体的形式被表达出来。

end this

卡方统计量

设矩阵 A m × n A_{m\times n} Am×n,记 B i j = ( ∑ i = 1 m A i j ) × ( ∑ j = 1 n A i j ) ∑ i = 1 m ∑ i = 1 n A i j B_{ij} = \frac{(\sum_{i=1}^mA_{ij})\times (\sum_{j=1}^nA_{ij})}{\sum_{i=1}^m\sum_{i=1}^nA_{ij}} Bij=i=1mi=1nAij(i=1mAij)×(j=1nAij),定义卡方值如下:
χ 2 = ∑ i = 1 m ∑ j = 1 n ( A i j − B i j ) 2 B i j \chi^2 = \sum_{i=1}^m\sum_{j=1}^n\frac{(A_{ij}-B_{ij})^2}{B_{ij}} χ2=i=1mj=1nBij(AijBij)2
请利用Numpy对给定的矩阵 A A A计算 χ 2 \chi^2 χ2

np.random.seed(0)
A = np.random.randint(10, 20, (8, 5))
B = (A.sum(axis=0)*A.sum(axis=1).reshape(-1,1))/A.sum()
K2 = ((A-B)**2/B).sum()
K2
11.842696601945802

注意 上面B公式的实现,是通过矩阵的乘法,这方面的话,还得去补一补线代的课。其他的到还好没什么东西。

改进矩阵的计算性能

Z Z Z m × n m×n m×n的矩阵, B B B U U U分别是 m × p m×p m×p p × n p×n p×n的矩阵, B i B_i Bi B B B的第 i i i行, U j U_j Uj U U U的第 j j j列,下面定义 R = ∑ i = 1 m ∑ j = 1 n ∥ B i − U j ∥ 2 2 Z i j \displaystyle R=\sum_{i=1}^m\sum_{j=1}^n\|B_i-U_j\|_2^2Z_{ij} R=i=1mj=1nBiUj22Zij,其中 ∥ a ∥ 2 2 \|\mathbf{a}\|_2^2 a22表示向量 a a a的分量平方和 ∑ i a i 2 \sum_i a_i^2 iai2

现有某人根据如下给定的样例数据计算 R R R的值,请充分利用Numpy中的函数,基于此问题改进这段代码的性能。

## 以下是提供的原方法
np.random.seed(0)
m, n, p = 100, 80, 50
B = np.random.randint(0, 2, (m, p))
U = np.random.randint(0, 2, (p, n))
Z = np.random.randint(0, 2, (m, n))
def solution(B=B, U=U, Z=Z):
    L_res = []
    for i in range(m):
        for j in range(n):
            norm_value = ((B[i]-U[:,j])**2).sum()
            L_res.append(norm_value*Z[i][j])
    return sum(L_res)
solution(B, U, Z)

下面对其进行改进

由于前面提供的分量平方和的公式,可以将式子改为

Y i j = ∥ B i − U j ∥ 2 2 Y_{ij} = \|B_i-U_j\|_2^2 Yij=BiUj22,则 R = ∑ i = 1 m ∑ j = 1 n Y i j Z i j \displaystyle R=\sum_{i=1}^m\sum_{j=1}^n Y_{ij}Z_{ij} R=i=1mj=1nYijZij

因此后面讨论 Y ( i j ) Y_(ij) Y(ij)是怎么推导出来的

latex公式乱码,mark一下

因此这里将改进公式应用于矩阵的乘法

(((B**2).sum(1).reshape(-1,1) + (U**2).sum(0) - 2*B@U)*Z).sum()
100566

连续整数的最大长度

输入一个整数的Numpy数组,返回其中递增连续整数子数组的最大长度,正向是指递增方向。例如,输入[1,2,5,6,7],[5,6,7]为具有最大长度的连续整数子数组,因此输出3;输入[3,2,1,2,3,4,6],[1,2,3,4]为具有最大长度的连续整数子数组,因此输出4。请充分利用Numpy的内置函数完成。(提示:考虑使用nonzero, diff函数)

f = lambda x:np.diff(np.nonzero(np.r_[1,np.diff(x)!=1,1])).max()
f([1,2,5,6,7])
f([3,2,1,2,3,4,6])

在使用np.diff(x)!=1进行判断是,获得是数据是布尔值,在使用列表合并的时候,[1,np.diff(x),1]输出的结果依旧是有整数有布尔array,但是使用了np.r_之后获得数据中原来的布尔array变成了数字。

其中的方法是妙的。

对其中的每一步分别拆解,需要知道的是使用np.r_之后,布尔数据会自动转化为数值数据

在使用np.diff(x)!=1进行判断是,获得是数据是布尔值,在使用列表合并的时候,[1,np.diff(x),1]输出的结果依旧是有整数有布尔array,但是使用了np.r_之后获得数据中原来的布尔array变成了数字。

其中的方法是妙的。

对其中的每一步分别拆解,需要知道的是使用np.r_之后,布尔数据会自动转化为数值数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值