python中除以0的处理方法

优快云-blog-除以0问题
> 这篇blog用于记录如何在python里处理除以0的问题。 > 遇到的问题:在写矩阵运算,机器学习的过程中,会遇到矩阵相除的问题,之前的处理方法是在除法之前对每个元素逐个检查,但这样会导致无法利用numpy的并行计算的能力,最终导致计算速度大幅下降。

这个网站里提供里很好的讨论和指导https://www.codenong.com/26248654/

下面分别展示了三种处理除以0的方法,以个人愚见:

  • 第一种方法比较普遍和通用(这个通用指换到其他语言或者脱离numpy,这个思路也感觉是可以的)
  • 第二种方法是最好的处理方法,对NaN和inF分别进行了处理
  • 第三种方法是最简洁的处理方法,只要一行,在对错误的情况理解比较清楚的时候,用这个也不错。

除以0会导致的两种错误

import numpy as np
# 计算的被除数A,以及除数B
arrayA = np.arange(9).reshape(3,3)
arrayA[0,2]=0
arrayA[2,0]=-2
arrayB = np.array([[1,4,0],
                    [5,0,6],
                    [0,7,2]])
arrayC = arrayA / arrayB
print("arrayA:\n", arrayA)
print("arrayB:\n", arrayB)
print("*****************")
print("arrayA / arrayB\n",arrayC)
arrayA:
 [[ 0  1  0]
 [ 3  4  5]
 [-2  7  8]]
arrayB:
 [[1 4 0]
 [5 0 6]
 [0 7 2]]
*****************
arrayA / arrayB
 [[0.         0.25              nan]
 [0.6               inf 0.83333333]
 [      -inf 1.         4.        ]]

D:\Anaconda\lib\site-packages\ipykernel_launcher.py:8: RuntimeWarning: divide by zero encountered in true_divide
  
D:\Anaconda\lib\site-packages\ipykernel_launcher.py:8: RuntimeWarning: invalid value encountered in true_divide

首先我们展示在除法计算的过程中,出现错误的类型主要可以分为两种0/0,以及1/0

  • 对于0/0 的类型,得到的结果是Nan
  • 对于1/0 的类型,得到的结果是Inf(注意还有-inf)

思路一:分而治之

这个方法主要是提取了零元素和非零元素的位置,然后对非零元素进行计算,对零元素直接置约定的值。
但这个方法没有对两种除以0的错误类型分别进行操作,如果需要分开,则需要再进一步细分,分为三步:

  1. 对A和B都是非零元素操作
  2. 对A是非零,B是零元素进行操作
  3. 对A是零元素,B也是零元素进行操作
myOwnValue = 0 # 设置除数为0需要赋的值
arrayC = np.zeros(arrayA.shape)
idxNonZeros = np.where(arrayB!=0) # 得到一个2x7的矩阵,分别对应了7个非零元素的位置
idxZeros = np.where(arrayB==0)  # 得到一个2x2的矩阵,分别对应2个零元素的位置

# 除法按两步进行操作,首先是非零元素,随后计算零元素
# division in two steps: first with nonzero cells, and then zero cells
arrayC[idxNonZeros] = arrayA[idxNonZeros] / arrayB[idxNonZeros]
arrayC[idxZeros] = myOwnValue # 若约定为0是不需要这一步的,但如果约定不为0,例如为一极大值,则是必须的

print("*****************")
print("arrayA / arrayB\n",arrayC)
*****************
arrayA / arrayB
 [[0.         0.25       0.        ]
 [0.6        0.         0.83333333]
 [0.         1.         4.        ]]

思路二 先计算再解决(设计警告处理)

第一行的errstate是对浮点数错误的处理方式进行操作的上下文管理器

Context manager for floating-point error handling

顺手记录一下里面可以写的错误类型:

  • divide 除数为0的错误
  • invalid 无效浮点数的错误
  • over 浮点数溢出
  • under 浮点数向下溢出(under-flow)
with np.errstate(divide='ignore', invalid='ignore'):
    arrayC = arrayA / arrayB
    # 可以参考的对错误处理的方式
#     arrayC[arrayC == np.inf] = 0  # 对inf的错误进行修正,不会修正-inf
    arrayC[~ np.isfinite(arrayC)] = 0 # 对 -inf, inf, NaN进行修正,置为0
#     arrayC = np.nan_to_num(arrayC)  # 对-inf, inf, NaN的错误进行修正了果置0,对inf置大数,
                                      # 但返回的为浮点数,不是True_division
    
print("*****************")
print("arrayA / arrayB\n",arrayC)
*****************
arrayA / arrayB
 [[0.         0.25       0.        ]
 [0.6        0.         0.83333333]
 [0.         1.         4.        ]]

思路三 调用numpy的除法函数

事实上,numpy早就帮你考虑到除法问题了,所以提供了一个针对矩阵的除法函数,numpy.divide()
但这个方法依然只能统一处理两种除法为0错误,无法识别inf的问题,但是最简洁。

若输出处out,不指定dtype类型为浮点数,会出现错误(把浮点数赋给整数,精度丢失)
这里如果不指定out也会出现一样的结果,但不确定函数内部是不是默认初始值为0

arrayC = np.divide(arrayA, arrayB, out=np.zeros_like(arrayA, dtype=np.float64), where=arrayB!=0)
print("*****************")
print("arrayA / arrayB\n",arrayC)
*****************
arrayA / arrayB
 [[0.         0.25       0.        ]
 [0.6        0.         0.83333333]
 [0.         1.         4.        ]]
### 解决CentOS 7更换阿里Yum源后无法解析的问题 当遇到`Could not resolve host` 或 `404错误`时,这通常意味着系统尝试访问的服务器名称未能成功转换成IP地址,或者是请求的页面不存在。对于CentOS 7,在其生命周期结束后,官方停止了对其的支持和维护,包括关闭官方的YUM源服务[^3]。 #### 修改主机名解析设置 为了确保能够正确解析到阿里的镜像站,可以编辑 `/etc/resolv.conf` 文件来指定DNS服务器: ```bash nameserver 223.5.5.5 nameserver 119.29.29.29 ``` 这两条记录指向的是阿里云提供的公共DNS服务,有助于提高域名解析的成功率和速度[^1]。 #### 替换默认的YUM源配置文件 下载并应用来自阿里云的最新YUM源列表至本地机器上。可以通过脚本自动化完成此过程,也可以手动操作如下所示: 进入yum.repos.d目录: ```bash cd /etc/yum.repos.d/ ``` 备份现有的repo文件以防万一: ```bash mv *.repo *.repo.bak ``` 创建新的aliyun.repo文件并将下面的内容粘贴进去: ```ini [base] name=CentOS-$releasever - Base - mirrors.aliyun.com failovermethod=priority baseurl=http://mirrors.aliyun.com/centos/$releasever/os/$basearch/ gpgcheck=1 enabled=1 gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 [updates] name=CentOS-$releasever - Updates - mirrors.aliyun.com failovermethod=priority baseurl=http://mirrors.aliyun.com/centos/$releasever/updates/$basearch/ gpgcheck=1 enabled=1 gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 [extras] name=CentOS-$releasever - Extras - mirrors.aliyun.com failovermethod=priority baseurl=http://mirrors.aliyun.com/centos/$releasever/extras/$basearch/ gpgcheck=1 enabled=1 gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 ``` 保存更改后的文件名为 aliyun.repo。 #### 清理缓存并重建数据库 执行以下命令清理旧的数据并重新构建元数据索引: ```bash sudo yum clean all sudo yum makecache fast ``` 最后再次测试是否能正常工作: ```bash sudo yum update ``` 如果一切顺利的话,则应该不会再看到之前的错误提示信息了[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值