不要相信 LLM 数学。

你使用 LLM 进行编程吗?希望你是,我也是。FFMPEG,数据采样,接口等等,还有很多无聊的事情。但是不要允许 LLM 编写你的数学。我准备了一些有趣的例子来展示不同 LLM 编写简单请求的代码。

ChatGPT中文站
A crazy mathematician (in the eyes of Stable Diffusion). Generated by Author.

该请求将是“编写一个FFT函数。”这是确切的请求(我尝试了几个请求,这是最好的结果)。

ChatGPT中文站
Image by Author

我们稍后会回到它。我将展示8个功能中,只有一个能正常工作(但不是100%)。我测试了约20个,但大多数有同样的错误。只有三个起作用。

一点理论

什么是FFT?FFT是使离散傅里叶变换(DFT)更快的方法。直接DFT需要O(N²)次操作。FFT需要O(N log N)次操作。

基本快速傅里叶变换是Cooley-Turkey算法。只需对一半的数据进行递归FFT即可执行它。就像这样:

ChatGPT中文站
Based on Wikipedia image.

为了测试和比较结果,我将使用常规的numpy FFT对2秒的带有声音和方波信号的信号进行处理。它应该看起来像这样:

ChatGPT中文站
Image by Author

让我们走!

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

其中最好的功能之一。有三个问题。

  1. 它很慢。迭代对Python来说很糟糕。
  2. 它接受了错误的输入。我需要一个numpy数组。
  3. 由于奇数和偶数使用不正确,它失去了部分分数。

正如您所见,结果接近于真实情况。

ChatGPT中文站
Image by Author

绝对是工作的代码,但我不建议在生产中使用这样的代码。

第二个例子也来自对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的幂的数组:

ChatGPT中文站
Image by Author

同样的错误在许多模型中非常普遍。这里是:

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的次方数。它可以让代码运行更快。

但是,让我们来看一下结果:

ChatGPT中文站
Image by Author

有什么不对吗?

是的。在增加数组大小的技巧之后,您需要重新规范响应。

没有它,结果将不正确。

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]。有问题吗?不要害羞,可以在此处或通过[电子邮件]提问!

同一文章作为视频:

2023-10-20 16:39:38 AI中文站翻译自原文