不要相信 LLM 数学。
你使用 LLM 进行编程吗?希望你是,我也是。FFMPEG,数据采样,接口等等,还有很多无聊的事情。但是不要允许 LLM 编写你的数学。我准备了一些有趣的例子来展示不同 LLM 编写简单请求的代码。
该请求将是“编写一个FFT函数。”这是确切的请求(我尝试了几个请求,这是最好的结果)。
我们稍后会回到它。我将展示8个功能中,只有一个能正常工作(但不是100%)。我测试了约20个,但大多数有同样的错误。只有三个起作用。
一点理论
什么是FFT?FFT是使离散傅里叶变换(DFT)更快的方法。直接DFT需要O(N²)次操作。FFT需要O(N log N)次操作。
基本快速傅里叶变换是Cooley-Turkey算法。只需对一半的数据进行递归FFT即可执行它。就像这样:
为了测试和比较结果,我将使用常规的numpy FFT对2秒的带有声音和方波信号的信号进行处理。它应该看起来像这样:
让我们走!
ChatGPT-3.5
def myfft(x, y):
n = len(x)
if n == 1:
y[0] = x[0]
else:
xe = np.zeros(n//2, dtype=np.complex)
xo = np.zeros(n//2, dtype=np.complex)
ye = np.zeros(n//2, dtype=np.complex)
yo = np.zeros(n//2, dtype=np.complex)
for i in range(n//2):
xe[i] = x[2*i]
xo[i] = x[2*i+1]
myfft(xe, ye)
myfft(xo, yo)
for k in range(n):
j = k % (n//2)
y[k] = ye[j] + np.exp(-2j*np.pi*k/n)*yo[j]
return y
其中最好的功能之一。有三个问题。
- 它很慢。迭代对Python来说很糟糕。
- 它接受了错误的输入。我需要一个numpy数组。
- 由于奇数和偶数使用不正确,它失去了部分分数。
正如您所见,结果接近于真实情况。
绝对是工作的代码,但我不建议在生产中使用这样的代码。
第二个例子也来自对ChatGPT-3.5的相同请求。
def fft_custom(x):
N = len(x)
if N <= 1:
return x
even = fft_custom(x[0::2])
odd = fft_custom(x[1::2])
t = np.exp(-2j * np.pi * np.arange(N) / N)
return np.concatenate([even + t[:N//2] * odd, even + t[N//2:] * odd])
看起来几乎一样,但它无法处理大小不是2的幂的数组:
同样的错误在许多模型中非常普遍。这里是:
Bing人工智能
def fft(x):
N = len(x)
if N <= 1:
return x
even = fft(x[0::2])
odd = fft(x[1::2])
T = [np.exp(-2j * np.pi * k / N) * odd[k] for k in range(N // 2)]
return [even[k] + T[k] for k in range(N // 2)] + \
[even[k] - T[k] for k in range(N // 2)]
克洛德
import numpy as np
def fft(x):
N = len(x)
if N == 1:
return x
even = fft(x[::2])
odd = fft(x[1::2])
T = [np.exp(-2j * np.pi * k / N) * odd[k] for k in range(N // 2)]
return np.concatenate([even + T, even - T])
ChatGPT-4
def fft(x):
N = x.size
if N <= 1:
return x
even = fft(x[::2])
odd = fft(x[1::2])
factor = np.exp(-2j * np.pi * np.arange(N) // N)
return np.concatenate([even + factor[:N//2] * odd,
even + factor[N//2:] * odd])
但是ChatGPT-4有时会生成出色的东西:
def _fft_recursive(x):
N = x.shape[0]
if N <= 1:
return x
even = _fft_recursive(x[::2])
odd = _fft_recursive(x[1::2])
T = np.exp(-2j * np.pi * np.arange(N) / N)
return np.concatenate([even + T[:N // 2] * odd,
even + T[N // 2:] * odd])
def fft_numpy_array(arr):
if not np.iscomplexobj(arr):
arr = arr.astype(np.complex128)
original_length = arr.shape[0]
next_power_of_2_length = 2 ** int(np.ceil(np.log2(original_length)))
padded_arr = np.zeros(next_power_of_2_length, dtype=arr.dtype)
padded_arr[:original_length] = arr
return _fft_recursive(padded_arr)[:original_length]
这是非常好看的代码。ChatGPT会将数组长度增加到下一个2的次方数。它可以让代码运行更快。
但是,让我们来看一下结果:
有什么不对吗?
是的。在增加数组大小的技巧之后,您需要重新规范响应。
没有它,结果将不正确。
Bard (巴德)
除了基于Gpt的LLM外,其他LLM在代码方面变得更差了。但更有趣。
def fft(x):
# Check if the input array is a numpy array.
if not isinstance(x, np.ndarray):
raise TypeError("The input array must be a numpy array.")
# Get the shape of the input array.
shape = x.shape
# Check if the input array is a one-dimensional array.
if len(shape) != 1:
raise ValueError("The input array must be a one-dimensional array.")
# Calculate the number of elements in the input array.
n = shape[0]
# Create a complex array to store the FFT coefficients.
y = np.zeros(n, dtype=complex)
# Calculate the FFT coefficients.
for k in range(n):
for j in range(n):
y[k] += x[j] * np.exp(-2j * np.pi * k * j / n)
# Return the FFT coefficients.
return y
面掌。这不是快速傅里叶变换。不要骗我,吟游诗人!这是离散傅里叶变换!
无法翻译该文本,因为它不是完整的句子或单词,可能是一个缩写或错字。请提供更多上下文或正确的文本。
下一个是来自YaGPT的。这是来自Yandex的LLM模型。
def bptf(arr):
fft = np.zeros((len(arr), len(arr)))
for i in range(len(fft)):
fft[i, i] = 1
n = len(fft)
half = n // 2
for j in range(half):
for k in range(n//2):
fft[j, k] = arr[j]
for i in range(k, n-1):
fft[j, i] += np.cos(2 * np.pi * i / n) * fft[j+1, i-1]
for i in reversed(range(2, n)):
fft[j, i] -= np.cos(2 * np.pi * (i-1) / n) * fft[j-1, i+1]
return fft
而且。当它尝试生成数组时,此代码将失败。
但是,这个循环看起来很可疑。这是你的作业。请计算它是否是复杂度o(N²)还是o(N⁴)。
HuggingFace聊天
而最终是HugginFace Chat。它非常出色。一开始,它给了我Cython代码。之后,代码中包含了很多错误,不能运行。
我的最后一次尝试:
def fft(array):
n = len(array)
# Create an array of complex conjugates
conjugate_arr = np.conjugate(array)
if array.dtype == 'complex': # If the original data was complex already, no need to create a new array
conjugate_arr = array
return np.dot(array, conjugate_arr).real / n * n
道德。
好的。这对我来说非常有趣。请选择最佳解决方案!
以下是故事的小寓言:
当然,在项目中使用LLM进行数学计算是可以的。但是在这么做的时候,你需要:
- 了解所有您要求LLM生成的数学内容。不要要求生成您不了解的内容。您将永远找不到错误。
- 进行测试以验证结果。
- 了解您所需要的算法的参数。算法的速度,内存使用量等等。
尝试运行同一个请求几次。结果会不同。进行比较。
你觉得这个有趣吗?不要忘记订阅[LinkedIn,YouTube,Twitter]。有问题吗?不要害羞,可以在此处或通过[电子邮件]提问!
同一文章作为视频: