V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NoOneNoBody
V2EX  ›  OpenAI

对智谱清言有点失望

  •  
  •   NoOneNoBody · 280 天前 · 1400 次点击
    这是一个创建于 280 天前的主题,其中的信息可能已经有所发展或是发生改变。

    GLM-4 首先,它不知道“智谱清言”是什么,哈哈

    “有一个 dataframe ,index 为整数,已经排序,所有值均为浮点类型,求其中两列,假设名为 a,b ,它们是否相交,a 上穿 b 为 1 ,a 下穿 b 为-1 ,无相交为 0 ,返回一个 series ,使用 Numba 加速” 这段话,chatgpt3.5 给我的是代码,智谱清言给我的是计算结果……结果,就是它自己生成了一个 datframe 并计算了,把结果回答给我,很晕

    chatgpt3.5 虽然给我的代码是错的,但受它启发,写了个简单函数完成了,这个函数是向量化的

    def is_cross(arr:np.ndarray, arr_ref:np.ndarray)->np.ndarray:
        '''
        求两个 array 是否有相交\n
        返回:一个 numpy array\n
        其中 0 表示没有相交,1 表示 arr 上穿 arr_ref ,-1 则表示下穿\n
        \n
        原理:求两个 array 的差并获取符号数列,求取这个符号数列相邻的差,再次获取这个差值数列的符号为返回结果\n
        相邻符号如果相同差为 0 ,就是无相交;符号从-变 0/+,为上穿,差值为+1/+2 ;符号从+变 0/-,为下穿,差值为-1/-2\n
        符号从 0 变为有符号,性质一样,结果也符合需求\n
        所以再次求取符号则为结果
        '''
        return np.sign(np.ediff1d(np.sign(arr-arr_ref), to_begin=0))
    
    2 条回复    2024-02-17 01:40:28 +08:00
    cwyalpha
        1
    cwyalpha  
       279 天前 via iPhone
    要解决这个问题,我们可以编写一个 Python 函数,该函数接受一个 DataFrame 和两列名作为输入,并返回一个 Series ,表示列`a`和列`b`的穿越情况。然后,我们将使用 Numba 装饰器`@jit`来加速这个函数。

    1. **定义函数**:函数将遍历 DataFrame 的行,比较每一行的`a`和`b`列值与其上一行的值,以确定是否发生了上穿或下穿。
    2. **使用 Numba 加速**:通过在函数定义前添加`@jit`装饰器来加速函数。Numba 是一个开源的 JIT ( Just-In-Time )编译器,它可以显著提高 Python 代码的执行速度,特别是对于数值计算和科学计算非常有效。
    3. **返回 Series**:根据穿越情况,为每个时间点返回 1 (上穿)、-1 (下穿)或 0 (无相交)。

    下面是实现这个逻辑的代码示例。首先,确保你已经安装了`numba`和`pandas`库。

    ```python
    import pandas as pd
    import numpy as np
    from numba import jit

    # 示例 DataFrame 创建,仅供参考
    # df = pd.DataFrame({'a': np.random.rand(10), 'b': np.random.rand(10)})

    @jit(nopython=True)
    def calculate_cross_over(a, b):
    result = np.zeros(len(a))
    for i in range(1, len(a)):
    if a[i] > b[i] and a[i-1] <= b[i-1]:
    result[i] = 1 # a 上穿 b
    elif a[i] < b[i] and a[i-1] >= b[i-1]:
    result[i] = -1 # a 下穿 b
    # 其他情况默认为 0 ,无需额外处理
    return result

    def cross_over_series(df, col_a, col_b):
    a_values = df[col_a].values
    b_values = df[col_b].values
    cross_over_values = calculate_cross_over(a_values, b_values)
    return pd.Series(cross_over_values, index=df.index)

    # 使用函数的示例
    # result_series = cross_over_series(df, 'a', 'b')
    # print(result_series)
    ```

    在这个代码中:
    - `calculate_cross_over`函数是使用 Numba JIT 编译的核心函数,它负责计算两列之间的穿越情况。
    - `cross_over_series`函数是一个封装函数,它接受 DataFrame 和列名作为输入,调用`calculate_cross_over`函数,并返回结果 Series 。

    请注意,由于 Numba 的`nopython`模式限制,我们直接在 Numba 函数中使用了 Numpy 数组而不是直接操作 DataFrame 。这是因为 Numba 最优化地支持 Numpy 数组计算。




    -------
    能否向量化地完成这个代码
    -------


    向量化的方法可以使用 Pandas 和 Numpy 的内置功能来实现,而不需要显式循环,这样可以提高计算效率并简化代码。下面是如何使用向量化方法来完成相交点检测的步骤:

    1. **计算差分**:首先,计算两列`a`和`b`的差分,即`a - b`。这将用于确定`a`是否在`b`之上或之下。
    2. **标记穿越点**:通过比较相邻元素的差分符号,我们可以找到穿越点。当差分从负变正时,表示`a`上穿`b`;从正变负时,表示`a`下穿`b`。
    3. **返回 Series**:最终,我们将创建一个 Series ,根据是否发生穿越以及穿越的方向来分配值( 1 代表上穿,-1 代表下穿,0 代表无穿越)。

    下面是实现这个方法的代码示例:

    ```python
    import pandas as pd
    import numpy as np

    def vectorized_cross_over(df, col_a, col_b):
    # 计算 a 和 b 的差值
    diff = df[col_a] - df[col_b]
    # 计算差值的符号变化(正负变化),使用 np.sign(diff)获取符号,并通过 diff 计算其差分以检测变化
    sign_changes = np.sign(diff).diff()

    # 上穿为 1 ,下穿为-1 ,无穿越为 0
    # np.sign(diff).diff() == 2 表示从负到正的变化,即上穿
    # np.sign(diff).diff() == -2 表示从正到负的变化,即下穿
    crossover_series = pd.Series(0, index=df.index) # 初始化为 0
    crossover_series[sign_changes == 2] = 1 # 上穿
    crossover_series[sign_changes == -2] = -1 # 下穿

    return crossover_series

    # 示例 DataFrame 创建
    # df = pd.DataFrame({'a': np.random.rand(10), 'b': np.random.rand(10)})

    # 使用函数
    # result_series = vectorized_cross_over(df, 'a', 'b')
    # print(result_series)
    ```

    这段代码完全使用向量化操作来检测`a`和`b`列的穿越情况,避免了显式循环,从而提高了性能。需要注意的是,由于使用了`diff()`方法,第一个元素将总是被标记为 0 (无穿越),因为它没有前一个元素来比较。







    GPT4 的回答不知道是否正确
    NoOneNoBody
        2
    NoOneNoBody  
    OP
       279 天前
    @cwyalpha #1
    原理是一样的,np.ediff1d 和 pd.Series.diff 是一样的,只是 np.ediff1d 计算少了第一个值,补个 to_begin=0 参数而已
    我起初也是用 diff(),后来才改成兼容性更高的 numpy

    不过这里 gpt 漏了一个逻辑,相邻两个其中一个是 0 ,另一个是+1/-1 ,这个 diff 结果是+1 或-1 ,不是+2/-2
    用==2/==-2 会漏掉这个
    0 就是两条线在同一个点刚好相等的情况,如 a=[1,2,3,4], b=[3,2,1,0],第二个点是刚好相等的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1162 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 23:05 · PVG 07:05 · LAX 15:05 · JFK 18:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.