如何调试 numpy 掩码

2024-05-14

这个问题与this one https://stackoverflow.com/q/73672739/11004423.

我有一个正在尝试矢量化的函数。这是原来的函数:

def aspect_good(angle: float, planet1_good: bool, planet2_good: bool):
    """
    Decides if the angle represents a good aspect.
    NOTE: returns None if the angle doesn't represent an aspect.
    """

    if 112 <= angle <= 128 or 52 <= angle <= 68:
        return True
    elif 174 <= angle <= 186 or 84 <= angle <= 96:
        return False
    elif 0 <= angle <= 8 and planet1_good and planet2_good:
        return True
    elif 0 <= angle <= 6:
        return False
    else:
        return None

这就是我到目前为止所拥有的:

def aspects_good(
    angles: npt.ArrayLike,
    planets1_good: npt.ArrayLike,
    planets2_good: npt.ArrayLike,
) -> npt.NDArray:
    """
    Decides if the angles represent good aspects.

    Note: this function was contributed by Mad Physicist. Thank you.
    https://stackoverflow.com/q/73672739/11004423

    :returns: an array with values as follows:
        1 – the angle is a good aspect
        0 – the angle is a bad aspect
       -1 – the angle doesn't represent an aspect
    """
    result = np.full_like(angles, -1, dtype=np.int8)

    bad_mask = np.abs(angles % 90) <= 6
    result[bad_mask] = 0

    good_mask = (np.abs(angles - 120) <= 8) |\
                (np.abs(angles - 60) <= 8) |\
                ((np.abs(angles - 4) <= 4) & planets1_good & planets2_good)
    result[good_mask] = 1

    return result

它没有按预期工作,但是,我用 pytest 编写了一个测试:

def test_aspects_good():
    tests = np.array([
        [120, True, False, True],
        [60, True, False, True],
        [180, True, False, False],
        [90, True, False, False],

        [129, True, False, -1],
        [111, True, False, -1],
        [69, True, False, -1],
        [51, True, False, -1],
        [187, True, False, -1],
        [173, True, False, -1],
        [97, True, False, -1],
        [83, True, False, -1],

        [0, True, True, True],
        [0, True, False, False],
        [0, False, True, False],
        [0, False, False, False],

        [7, False, False, -1],
        [7, True, True, True],
        [9, True, True, -1],
    ])

    angles = tests[:, 0]
    planets1_good = tests[:, 1]
    planets2_good = tests[:, 2]
    expected = tests[:, 3]

    result = aspects_good(angles, planets1_good, planets2_good)
    assert np.array_equal(result, expected)

它失败了,说 False,数组不同。

这里我有result and expected数组并排组合:

array([[ 1,  1],
│      [ 1,  1],
│      [ 0,  0],
│      [ 0,  0],
│      [-1, -1],
│      [-1, -1],
│      [-1, -1],
│      [-1, -1],
│      [-1, -1],
│      [-1, -1],
│      [-1, -1],
│      [-1, -1],
│      [ 0,  1],
│      [ 0,  0],
│      [ 0,  0],
│      [ 0,  0],
│      [-1, -1],
│      [-1,  1],
│      [-1, -1]])

注意:第一列是result数组,第二个是expected。正如您所看到的,它们有两个地方不同。现在问题来了“如何调试这个?”通常我会使用调试器,并逐步执行每个 if/elif/else 条件。但我不知道如何调试 numpy 掩码。


这个问题似乎是三件事的结合:

  1. Numpy 在整个数组中使用同构类型。

    你会发现tests.dtype is dtype('int64') or dtype('int32')取决于您的架构。这意味着包含的列planet1_good and planet2_good也是整数,而不是布尔值。

  2. 按位与 (&) is not逻辑运算符。

    按位 AND 运算将返回具有最大输入类型的结果。具体来说,对于结果<=, which is一个布尔值,和一个int数组,结果将是int。这意味着你可以做类似的事情np.array([1, 2]) & np.array([True, True]) to get array([1, 0]), not array([True, False]).

  3. Numpy 通过 dtype 区分布尔掩码和花式索引,即使花式索引仅包含零和一。如果你有一个 2 元素数组,x, then x[[True, True]] = 1分配1的两个元素x。然而,x[[1, 1]] = 1分配1只到第二个元素x.

这基本上就是这里发生的事情。bad_mask是一个布尔掩码,并且完全按照您的预期工作。然而,good_mask与几个整数数组进行 AND 运算,因此成为包含 0 和 1 的整数数组。表达方式result[good_mask] = 1实际上是分配第一个和第二个元素result to be 1,它偶然对应于您的两个测试。其余True结果不能也不会被分配1.

有几种方法可以解决这个问题,按优先顺序降序列出(我最喜欢的在顶部):

  1. 将所有数组转换为正确类型的 numpy 数组。现在你的函数不符合它接受任何类似数组的约定。如果您传递一个列表angles, 你会得到TypeError: unsupported operand type(s) for %: 'list' and 'int'。这是一个相当惯用的方法:

    angles = np.asanyarray(angles)
    planets1_good = np.asanyarray(planets1_good, dtype=bool)
    planets2_good = np.asanyarray(planets2_good, dtype=bool)
    
    result = np.full_like(angles, -1, dtype=np.int8)
    
    bad_mask = np.abs(angles % 90) <= 6
    result[bad_mask] = 0
    
    good_mask = (np.abs(angles - 120) <= 8) |\
                (np.abs(angles - 60) <= 8) |\
                ((np.abs(angles - 4) <= 4) & planets1_good & planets2_good)
    result[good_mask] = 1
    return result
    
  2. 确保这件事good_mask敷之前其实是个面膜。你还是应该转换angles,但其他数组将被自动转换&操作员:

    good_mask = ((np.abs(angles - 120) <= 8) |\
                 (np.abs(angles - 60) <= 8) |\
                 ((np.abs(angles - 4) <= 4) & planets1_good & planets2_good)).astype(bool)
    

    您也可以执行与您所做的类似的操作bad_mask:

    good_mask = (np.abs(angles % 60) <= 8) & (angles >= -8) & (angles <= 128)
    
  3. 将掩码转换为索引,这不会关心原始数据类型:

    result[np.flatnonzero(good_mask)] = 1
    
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何调试 numpy 掩码 的相关文章

随机推荐

  • 检查Windows电源管理是否关闭了显示器

    如何在 Windows 7 和 XP 中以编程方式检查 Windows 电源管理 是否已关闭显示屏 如果能收到一个活动就更好了 我不认为 XP 可以做到这一点 Windows 7 中有各种与电源管理相关的好东西 这Windows API 代
  • git 可以与 Xcode 集成吗?

    有没有办法将 git 存储库与 Xcode 内置的 SCM 功能一起使用 Xcode 4 原生支持 git WWDC 2010 上的开发者工具国情咨文演讲 在这里了解更多 Xcode 4 中的新增功能 http developer appl
  • 在服务器桌面会话上捕获屏幕

    我开发了一个 GUI 测试框架 可以按计划对我们公司网站进行集成测试 当出现问题时 它会截取桌面等内容 它在专用 Windows Server 2008 上的登录用户上运行 无人值守 问题是在我已断开远程桌面会话连接的桌面上截取屏幕截图 我
  • java中如何知道一条sql语句是否执行了?

    我想知道这个删除语句是否真的删除了一些东西 下面的代码总是执行 else 是否删除了某些内容 执行此操作的正确方法是什么 public Deleter String pname String pword try PreparedStatem
  • 如何使用 jQuery 在按下按钮后保持按钮处于活动状态

    我见过一些非常相似的问题 但一直无法找到我正在寻找的答案 我已经确定了解决方法 但想知道执行该任务的正确方法 我想要的是单击按钮并使活动状态保持不变 下一次单击将切换状态 这是所需的 我真正需要知道的是如何解决 uiButton activ
  • 更改方向时更改 UITableViewCell 高度

    我有一个 UITableView 其中包含可变高度 UILabels 的单元格 我能够计算标签需要使用的最小高度sizeWithFont constrainedToSize lineBreakMode 首次加载表视图时效果很好 当我旋转表格
  • 当标题中包含“&”时,电子邮件标题无法正确显示,如何在 JavaScript 中修复?

    我有一些代码以以下格式显示文章标题列表 简短描述和作者姓名 标题 作者姓名 描述 作者的姓名和描述与此处无关 因为它们始终显示正确 大多数标题也可以正确显示 以下是一些虚构的示例 关于银行业务您需要了解的最重要的一件事 作者姓名 正确显示
  • npm install 没有拉入 devDependency

    我有 npm v 1 2 32 当我跑步时 npm 安装 mongo migrate 它不安装 mongodb 这是一个 devDependency 我究竟做错了什么 虽然与这个问题没有直接关系 但有些人可能有兴趣知道如果环境变量NODE
  • 带有闭包的 JavaScript 性能

    var name function n var digits one two three four return digits n var namenew function digits one two three four return
  • 使用 OkHttp 下载损坏的文件

    我编写的下载文件的方法总是会产生损坏的文件 public static String okDownloadToFileSync final String link final String fileName final boolean te
  • 找不到 React/RCTEventEmitter.h 文件

    我正在尝试使用独立的 Expo 应用程序来实现 PushNotificationIOS 我正在运行 SDK 21 0 0 React Native 0 48 我正进入 状态React RCTEventEmitter file not fou
  • 如何在 Mac 的任何 webkit 中隐藏父圆角的画布内容?

    我有一个父母div带有圆角 其中包含canvas div div
  • 如何在Excel中识别给定月份的第一,第二等星期一或一周中的其他日期

    我在网上查了一下 但公式看起来很复杂 有什么巧妙的建议吗 例如 我需要一个公式来确定哪个日期是 2014 年 8 月的第一个星期一 类似于第二个星期一的使用 等等 谢谢 一般来说 你可以找到n 第一个x给定的一天M and Y用这个公式 D
  • Vim 函数插入带有传递参数的静态文本

    背景 I m interested in writing a function that assigned to keyboard shortcut s when invoked would 采取用户参数 计算值反映80 string le
  • ASP.NET MVC运行IIS7部署问题

    我在将 ASP NET MVC 应用程序部署到 IIS7 时遇到问题 我有一个使用 ASP NET MVC Beta 1 创建的 MVC 项目 它仅包含未修改的默认模板 该应用程序在 VS2008 中运行得很好 但是当我将其发布到本地 II
  • Woocommerce 获取产品

    我使用以下代码从我的 WordPress 网站中的 WooCommerce 获取产品类别列表
  • 如何在动态执行的代码字符串中使用inspect.getsource?

    如果我在文件中有这段代码 import inspect def sample p1 print p1 return 1 print inspect getsource sample 当我运行脚本时 它按预期工作 在最后一行 源代码sampl
  • 维护一组通用的 Eclipse 首选项

    每当我切换工作区 Eclipse 安装时 我都需要复制 重做首选项 编译器设置 字体大小 系列 代码格式化程序 java代码模板 编辑器模板 代码清理 我想以统一的方式维护这些设置 最好是在源代码控制下 我怎样才能做到这一点 我知道创建新工
  • 如何从控制器访问片段中的片段?

    我有一个名为 cutleryCustomerSearch 的视图 其中包含 替换 一个片段 div div div div 在此片段中 我有一个表 我喜欢通过 ajax 更新它 table 我如何设置处理 ajax 请求的控制器方法的返回
  • 如何调试 numpy 掩码

    这个问题与this one https stackoverflow com q 73672739 11004423 我有一个正在尝试矢量化的函数 这是原来的函数 def aspect good angle float planet1 goo