你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了

在我们的生活中,大到天体观测、小到MP3播放器上的频谱,没有傅里叶变换都无法实现。通俗来讲,离散傅里叶变换(DFT)就是把一串复杂波形中分成不同频率成分。比如声

大家好,今天小编来为大家解答以下的问题,关于你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了,这个很多人还不知道,现在让我们一起来看看吧!

比如说声音,如果用录音机来显示声音的话,其实生活中大部分的声音都是非常复杂的,甚至是杂乱的。

通过傅里叶变换,可以将这些杂乱的声波转换成正弦波,这就是我们通常在音乐声谱图中看到的。

但在实际计算中,这个过程其实是非常复杂的。

如果将声波视为连续函数,则它可以唯一地表示为叠加的三角函数的堆栈。但在叠加过程中,各个三角函数的权重系数是不同的。有的应该增加,有的应该减少,有的甚至不应该增加。

傅里叶变换找到这些三角函数及其各自的权重。

难道不是巧合吗?这个搜索过程非常像神经网络。

神经网络的本质其实就是逼近一个函数。

难道不能通过训练神经网络来使用傅里叶变换吗?

这确实可行,最近有人在网上发布了他的训练过程和结果。

DFT=神经网络

如何训练神经网络?这位网友给出的思路是这样的:

首先,离散傅立叶变换(DFT)应该被视为一种人工神经网络。这是一个单层网络,没有偏差,没有激活函数,权重有特定值。其输出节点数等于傅里叶变换计算后的频率数。

具体方法如下:

这是一个DFT:

k表示每N个样本的循环数; N表示信号的长度;表示样本n 处的信号值。信号可以表示为所有正弦信号的总和。

yk 是一个复数值,给出信号x 中频率为k 的正弦信号的信息;根据yk 我们可以计算出正弦波的幅度和相位。

改成矩阵形式,就变成了这样:

这里给出了特定值k 的傅立叶值。

但通常情况下,我们要计算全谱,即从[0,1,N-1]中得到k的值,可以用矩阵来表示(k按列增加,n按行增加) :

化简后我们得到:

你应该熟悉这一点,因为它是一个没有偏置和激活函数的神经网络层。

指数矩阵包含权重,可以称为复傅里叶权重。通常我们不知道神经网络的权重,但我们可以在这里。

不要使用复数。通常我们在神经网络中不使用复数。为了适应这种情况,我们需要将矩阵的大小加倍,使得左侧部分包含实数,右侧部分包含虚数。

将要

引入DFT,可得:

然后用实部(cos形式)表示矩阵的左半部分,用虚部(sin形式)表示矩阵的右半部分:

化简后我们可以得到:

将要

称为傅立叶权重;

需要注意的是,y^和y实际上包含相同的信息,但是y^

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了

没有使用复数,因此它的长度是y 的两倍。

换句话说,我们可以使用

或者

代表幅度和相位,但我们通常使用

现在,可以将傅立叶层添加到网络中。

用傅里叶权重计算傅里叶变换

现在可以使用神经网络来实现

,并使用快速傅立叶变换(FFT) 检查它是否正确。

将matplotlib.pyplot 导入为plty_real=y[:signal_length]y_imag=y[: signal_length:]tvals=np.arange(signal_length).reshape([-1, 1])freqs=np.arange(signal_length).reshape( [1, -1])arg_vals=2 * np.pi * tvals * freqs/signal_lengthsinusoids=(y_real * np.cos(arg_vals) – y_imag * np.sin(arg_vals))/signal_lengthreconstructed_signal=np.sum(sinusoids, axis=1)print(‘rmse:’, np.sqrt(np.mean((x – 重建信号)**2)))plt.subplot(2, 1, 1)plt.plot(x[0,])plt .title(‘原始信号’)plt.subplot(2, 1, 2)plt.plot(reconstructed_signal)plt.title(‘DFT后从正弦曲线重建的信号’)plt.tight_layout()plt.show()rmse: 2.3243522568191728e这个-15这个小误差值可以证明计算出来的结果就是我们想要的。

另一种方法是重建信号: import matplotlib.pyplot as plty_real=y[:signal_length]y_imag=y[: signal_length:]tvals=np.arange(signal_length).reshape([-1, 1])freqs=np .arange(signal_length).reshape([1, -1])arg_vals=2 * np.pi * tvals * freqs/signal_lengthsinusoids=(y_real * np.cos(arg_vals) – y_imag * np.sin(arg_vals))/signal_lengthreconstructed_signal=np.sum(正弦波, axis=1)print(‘rmse:’, np.sqrt(np.mean((x – 重建信号)**2)))plt.subplot(2, 1, 1)plt.plot ( x[0,])plt.title(‘原始信号’)plt.subplot(2, 1, 2)plt.plot(reconstructed_signal)plt.title(‘DFT后从正弦曲线重建的信号’)plt.tight_layout( ) plt.show()rmse: 2.3243522568191728e-15

最后可以看出,DFT后的正弦信号重构的信号与原始信号能够很好地重叠。

通过梯度下降学习傅里叶变换

现在是神经网络实际学习的部分。这一步不需要像之前那样预先计算权重值。

首先,使用FFT训练神经网络来学习离散傅里叶变换:

import tensorflow as tfsignal_length=32# 将权重向量初始化为train:W_learned=tf.Variable(np.random.random([signal_length, 2 * signal_length]) – 0.5)# 预期权重,用于比较:W_expected=create_fourier_weights(signal_length)losses=[]rmses=[]for i in range(1000): # 每次迭代生成一个随机信号: x=np.random.random([1, signal_length]) – 0.5 # 使用FFT: 计算预期结果fft=np.fft.fft( x) y_true=np.hstack([fft.real, fft.imag]) 与tf.GradientTape() 作为Tape: y_pred=tf.matmul(x, W_learned) 损失=tf.reduce_sum(tf.square(y_pred – y_true) ) # 通过梯度下降训练权重: W_gradient=Tape.gradient(loss, W_learned) W_learned=tf.Variable(W_learned – 0.1 * W_gradient)loss.append(loss) rmses.append(np.sqrt(np.mean((W_learned) – W_expected)**2)))最终损失值1.6738563548424711e-09最终权重rmse 值3.1525832404710523e-06

结果如上,证实了神经网络确实可以学习离散傅里叶变换。

训练网络学习DFT

除了使用快速傅里叶变换方法之外,还可以通过网络重构输入信号来学习DFT。 (类似于自动编码器)。

自动编码器(AE)是一种用于半监督学习和无监督学习的人工神经网络(ANN)。其功能是以输入信息为学习目标,对输入信息进行表征学习。 (表征学习)。

W_learned=tf.Variable(np.random.random([signal_length, 2 * signal_length]) – 0.5)tvals=np.arange(signal_length).reshape([-1, 1])freqs=np.arange(signal_length)。 reshape([1, -1])arg_vals=2 * np.pi * tvals * freqs/signal_lengthcos_vals=tf.cos(arg_vals)/signal_lengthsin_vals=tf.sin(arg_vals)/signal_lengthlosses=[]rmses=[]for i in范围(10000): x=np.random.random([1, signal_length]) – 0.5 tf.GradientTape() 作为tape: y_pred=tf.matmul(x, W_learned) y_real=y_pred[: 0:signal_length] y_imag=y_pred [:signal_length:] 正弦曲线=y_real * cos_vals – y_imag * sin_vals 重构信号=tf.reduce_sum(sinusoids, axis=1) 损失=tf.reduce_sum(tf.square(x – 重构信号)) W_gradient=Tape.gradient(loss, W_learned ) W_learned=tf.Variable(W_learned – 0.5 * W_gradient) Loss.append(loss) rmses.append(np.sqrt(np.mean((W_learned – W_expected)**2)))最终损失值4.161919455121241e-22最终权重’均方根值0.20243339269590094

让我们尝试改变输入幅度和相位。

W_learned=tf.Variable(np.random.random([signal_length, 2 * signal_length]) – 0.5)losses=[]rmses=[]for i in range(10000): x=np.random.random([1, signal_length]) – .5 与tf.GradientTape() 作为Tape: y_pred=tf.matmul(x, W_learned) y_real=y_pred[: 0:signal_length] y_imag=y_pred[: signal_length:] 幅度=tf.sqrt(y_real**2 + y_imag**2)/signal_length 相位=tf.atan2(y_imag, y_real) 正弦曲线=振幅* tf.cos(arg_vals + 相位) 重建信号=tf.reduce_sum(sinusoids, axis=1) 损失=tf.reduce_sum(tf.平方(x – 重建信号))W_gradient=Tape.gradient(损失,W_learned)W_learned=tf.Variable(W_learned – 0.5 * W_gradient)loss.append(损失)rmses.append(np.sqrt(np.mean((W_learned – W_expected)**2)))最终损失值2.2379359316633115e-21最终权重rmse 值0.2080118219691059

可以看出,重建后的信号又是一致的;

然而,和以前一样,输入幅度和相位的所得权重并不完全等于傅立叶权重(但非常接近)。

可以得出结论,虽然最终的权重不是最准确的,但也能得到局部最优解。

这样,神经网络就学习了傅里叶变换!

值得一提的是,该方法还存在问题:首先,它没有解释计算权重与真实傅里叶权重之间的差异;

此外,没有解释将傅立叶层放入模型中的好处。

原文链接:https://sidsite.com/posts/fourier-nets/

– 超过-

用户评论

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
作业是老师的私生子

我之前也对傅里叶变换一脸懵逼,看视频学也没怎么懂…这篇文章简直太牛逼了!直接用代码解释,一下子就豁然明朗了。

    有5位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
猫腻

神经网络真的好用啊,连这种枯燥的数学公式都能这么轻松搞定。我之前一直觉得数学和程序员是两码事,现在看来还有很多神奇的地方值得探索呢!

    有14位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
服从

30行代码就能学会傅里叶变换?感觉好夸张啊,这神经网络也太厉害了吧!不过我也想试试看能不能用代码理解它是怎么工作的…

    有7位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
断桥残雪

感觉这位写文章的太牛逼了,把复杂的数学理论用这么通俗易懂的方式展示出来,真的让人感触很深。希望以后能多看看他的文章!

    有9位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
素衣青丝

我搞计算机专业的,傅里叶变换确实很重要,不过说实话,这篇文章写的有点水…神经网络学了,是不是等于就懂了傅里叶变换?感觉有点忽悠的成分啊…

    有11位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
莫名的青春

这篇博客把知识点都罗列了一遍,然后用代码解释每个点,看得清清楚楚。我之前一直觉得学习数学是件苦差事,现在看来用编程也能解决很多问题呢!

    有20位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
蔚蓝的天空〃没有我的翅膀

虽然30行代码确实厉害,但我还是建议大家多看看传统教材和视频教程,这样才能更深入地理解傅里叶变换背后的原理。单纯依靠代码理解可能会比较肤浅。

    有9位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
海盟山誓总是赊

作者的写作风格很轻松幽默,文章也写的很有条理,把复杂的概念用通俗易懂的方式解释出来,真是太棒了!

    有14位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
高冷低能儿

我一直想学习傅里叶变换,但是感觉门槛很高。这篇博客给了我很大启发,用代码去理解它,感觉可行性更强一点!

    有15位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
北朽暖栀

这篇文章让我意识到,机器学习与数学的结合确实越来越紧密了。未来,我相信会有更多用代码来解释数学概念的优秀作品出现。

    有11位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
把孤独喂饱

我还是觉得单纯依靠代码解释傅里叶变换不太全面啊,毕竟是数学理论,需要更深入的理解。我更倾向于结合传统的学习方式。

    有14位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
自繩自縛

太赞了!我一直想尝试一下用编程语言来探索傅里叶变换,这篇博客给了我很好的思路和启发。我要试试看能不能用Python自己实现一个简单的傅里叶变换算法!

    有6位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
七夏i

神经网络真的厉害,把复杂的任务交给它感觉很简单。但我觉得学习傅里叶变换不应该只局限于代码层面,还是要理解其理论基础和应用场景,才能真正掌握它。

    有16位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
蹂躏少女

这篇文章让我对深度学习的强大之处更加深信不疑!其实我之前也对傅里叶变换有所耳闻,却一直觉得太复杂。现在看来,只要用神经网络就能轻松搞定!

    有15位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
孤街浪途

代码可以让我们更直观地理解傅里叶变换的过程,这确实是一种很好的学习方式。不过还是要牢记其背后的数学原理和理论知识,才能更好地应用于实际问题中。

    有20位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
久爱不厌

感觉这篇博客太有趣了,用图解+代码的方式讲解傅里叶变换,真的让人一目了然!之前我完全搞不懂这个概念,现在终于有点眉目了!

    有9位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
何必锁我心

这篇文章让我对神经网络有了更深入的了解。原来它不仅能用来分类图片、识别语音,还可以处理复杂的数学运算,简直太厉害了!

    有16位网友表示赞同!

你还不懂的傅里叶变换,神经网络只用了30多行代码就学会了
不浪漫罪名

我觉得这篇博客写得不错,很适合像我这样初次接触傅里叶变换的人阅读学习。虽然代码示例只有30行,但足以让我初步了解其基本原理和应用场景。

    有11位网友表示赞同!

原创文章,作者:小su,如若转载,请注明出处:https://www.sudun.com/ask/127160.html

(0)
小su's avatar小su
上一篇 2024年9月1日 下午10:30
下一篇 2024年9月1日 下午10:34

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注