关于使用频谱预测混合两个信号





5.00/5 (5投票s)
本文展示了如何以不同的比例将两个信号混合成第三个信号。
背景
为了理解频谱预测方程,可以制作的最简单的应用程序之一与信号有关。可能会提出的一个问题是:给定两个信号 A 和 B,如果第三个信号 M 必须以一定比例同时类似于这两个信号,那么它会是什么样子?例如,可能需要信号 M 类似于信号 A 23% 的比例,而类似于信号 B 剩余 77% 的比例。这正是频谱方程提供的,即获得这样一个中间信号的直接方法。此外,频谱预测方程也可以应用于矩阵(二维),也可以应用于具有两个或三个以上维度的数学对象。作为旁注,频谱预测于 2020 年发表在美国物理学学会的 Chaos 期刊上。在发表之前,该公式用于矩阵而不是信号,但似乎它也可以应用于一维对象以及多维对象。在继续阅读之前,请参阅频谱预测在信号方面可以做什么的实时演示。
公式
下面显示的主方程可用于将两个信号组合并缩放为第三个信号。这两个信号可以按照任何期望的比例进行混合。频谱预测可以应用于信号,如这里所示,或以图形表示,如这里所示。对于信号,频谱预测方程采用以下形式
其中 Max (Ai) 是在信号 A 上方找到的最大值,Max (Bi) 是在信号 B 的分量上方找到的最大值。Ai 和 Bi 也表示两个信号在位置 i 处的同源值。最后但并非最不重要的一点是,Max (d) 表示 Max (Ai) 和 Max (Bi) 之间的最大值。因此 d 的值可以在 0 和 Max (d) 之间取值。上述表达式在 JavaScript 中转换为如下所示
max = Math.max(maxA, maxB)
v = ((d/maxA)*tA[i])+(((max-d)/maxB)*tB[i]);
其中 tA 和 tB 是保存两个信号连续值的向量。变量 v 保存位置 i 处第三个信号的值。请注意,最大距离是两个信号上方的最大值。该方程的线性形式直接用于以下 JavaScript 实现。
Using the Code
为了举例说明,我选择 JavaScript 是因为它具有立即实验的可能性,但请注意,该示例已用 8 种不同的编程或脚本语言实现。考虑以下形式的两个信号 A 和 B
A ='10.3,23.4,44.8,63.2,44.1,35.1,46.5,62.6,50.4,28.9,24.7';
B ='18.8,43.1,52.2,45.5,46.8,46.6,67.9,66.3,70.4,62,39.7';
如果第三个信号 M 必须同时类似于信号 A 和 B,那么它会是什么样子?如果 M 必须以一定比例类似于信号 A 怎么办?通过应用频谱预测方程,可以设计一个简短的实现来获得一个中间 M 信号:
// Spectral forecast for signals
var tA = [];
var tB = [];
var A ='10.3,23.4,44.8,63.2,44.1,35.1,46.5,62.6,50.4,28.9,24.7';
var B ='18.8,43.1,52.2,45.5,46.8,46.6,67.9,66.3,70.4,62,39.7';
var M ='';
var tA = A.split(',');
var tB = B.split(',');
var maxA = Math.max.apply(null, tA);
var maxB = Math.max.apply(null, tB);
var max = Math.max(maxA, maxB)
var d = 33;
for(var i=0; i < tA.length; i++) {
var tmp = ((d/maxA)*tA[i])+(((max-d)/maxB)*tB[i]);
M += tmp.toFixed(2);
if(i < tA.length-1){M += ','}
}
document.write('Signal A:<br>'+A+'<br>');
document.write('Max(A[i]):'+maxA+'<hr>');
document.write('Signal M:<br>'+M+'<hr>');
document.write('Signal B:<br>'+B+'<br>');
document.write('Max(B[i]):'+maxB+'<hr>');
输出
信号 A
10.3,23.4,44.8,63.2,44.1,35.1,46.5,62.6,50.4,28.9,24.7
Max(A[i]):63.2
信号 M
15.37,35.12,51.12,57.17,47.89,43.08,60.35,67.91,63.72,48.03,33.99
信号 B
18.8,43.1,52.2,45.5,46.8,46.6,67.9,66.3,70.4,62,39.7
Max(B[i]):70.4
请注意,为便于演示,这两个信号的长度相同。上述实现从两个已知信号 A 和 B 生成第三个信号 M,距离 d = 33。请注意,max(d)(最大距离)是信号 A 和 B 上方的最大值。因此,信号 A 和 B 上方的最大值表示 100%。
绘制信号
然而,用这个频谱预测的小实现能做什么呢?一个稍微高级的版本,其中包含上述实现和一个 js 图表,可以准确地显示该方程的作用。考虑一些更长的信号,例如
var A ='10.3,23.4,44.8,63.2,44.1,35.1,46.5,62.6,50.4,28.9,24.7,
22.7,43.2,17.2,31.5,8.3,17.9,3.9,4.1,2.3';
var B ='18.8,43.1,52.2,45.5,46.8,46.6,67.9,66.3,70.4,62,39.7,
50.3,75.9,52.9,44.9,32,64.8,37.4,19.3,9.4';
由于这两个信号足够长,我们可以将它们和结果 M 绘制在同一个图表中进行视觉检查。因此,更高级的实现形式可以在这里找到。应用程序的最终结果可以在这里看到,有几个 d 的可变步骤。例如
上面的动画以动态方式展示了两个信号如何根据距离 (d) 以不同比例组合。这两个信号用红色表示,生成的信号用黑色表示,对应于用户实时设置的不同 d 值。
Magic
如果信号变得更长,更像波形怎么办?那么可以获得更高的分辨率,结果在视觉上更具动态性。这样的项目示例可以在这里找到,上面这个 JavaScript 应用程序的动画如下所示。因此,只有在此分辨率下,该方法的实用性才变得更加明显。
为了举例说明,这些演示是在互联网浏览器上使用预计算的波形作为信号进行的。问题是:频谱预测还有哪些其他用途?我们将来可能会从我们中的某个人那里发现这些用途。欢迎那些发现其他频谱预测用途的人撰写并讨论新想法。至此,信号的频谱预测方法就结束了。
代码项目
到目前为止,所有演示都是用 JavaScript 完成的。然而,正如本文背景部分所述,这些演示是用八种编程和脚本语言完成的,即:C#、VB、PHP、Perl、Ruby、Java、Javascript 和 Python。因此,对于那些希望只下载他们首选编程或脚本语言的开源实现的人,这里是存储库列表
// Spectral forecast for signals in C#
using System;
public class SpectralForecast
{
public static void Main(string[] args)
{
string A = "10.3,23.4,44.8,63.2,44.1,35.1,46.5,62.6,50.4,28.9,24.7";
string B = "18.8,43.1,52.2,45.5,46.8,46.6,67.9,66.3,70.4,62,39.7";
string[] nA = A.Split(',');
string[] nB = B.Split(',');
double maxA = 0;
double maxB = 0;
string M = "";
double d = 33;
double v = 0;
double[] tA = new double[nA.Length];
double[] tB = new double[nB.Length];
for(int i=0; i < nA.Length; i++)
{
tA[i] = double.Parse(nA[i]);
tB[i] = double.Parse(nB[i]);
if (tA[i] > maxA){maxA = tA[i];}
if (tB[i] > maxB){maxB = tB[i];}
}
double maxAB = Math.Max(maxA, maxB);
for(int i=0; i < tA.Length; i++) {
v = ((d/maxA)*tA[i])+(((maxAB-d)/maxB)*tB[i]);
M += Math.Round(v, 2);
if(i < tA.Length-1){M += ',';}
}
Console.WriteLine (M);
}
}
' Spectral forecast for signals in VB
Sub main()
Dim tA() As String
Dim tB() As String
A = "10.3,23.4,44.8,63.2,44.1,35.1,46.5,62.6,50.4,28.9,24.7"
B = "18.8,43.1,52.2,45.5,46.8,46.6,67.9,66.3,70.4,62,39.7"
M = ""
tA = Split(A, ",")
tB = Split(B, ",")
For i = 0 To UBound(tA)
If (tA(i) > maxA) Then maxA = tA(i)
If (tB(i) > maxB) Then maxB = tB(i)
If (maxA > Max) Then Max = maxA
If (maxB > Max) Then Max = maxB
Next i
d = 33
For i = 0 To UBound(tA)
v = ((d / maxA) * tA(i)) + (((Max - d) / maxB) * tB(i))
M = M & Round(v, 2)
If (i < UBound(tA) - 1) Then M = M & ","
Next i
s = s & "Signal A: " & A & vbCrLf
s = s & "Max(A[i]):" & maxA & vbCrLf
s = s & "Signal M: " & M & vbCrLf
s = s & "Signal B: " & B & vbCrLf
s = s & "Max(B[i]):" & maxB & vbCrLf
MsgBox s
End Sub
// Spectral forecast for signals in PHP
$tA = [];
$tB = [];
$d = 33;
$A ='10.3,23.4,44.8,63.2,44.1,35.1,46.5,62.6,50.4,28.9,24.7';
$B ='18.8,43.1,52.2,45.5,46.8,46.6,67.9,66.3,70.4,62,39.7';
$M ='';
$tA = explode(",", $A);
$tB = explode(",", $B);
$maxA = Max($tA);
$maxB = Max($tB);
$max = Max($maxA, $maxB);
for($i=0; $i < count($tA); $i++) {
$v = (($d/$maxA)*$tA[$i])+((($max-$d)/$maxB)*$tB[$i]);
$M .= strval(round($v,2));
if($i < count($tA)-1){$M .= ',';}
}
echo $M;
# Spectral forecast for signals in Perl
my $A = '10.3,23.4,44.8,63.2,44.1,35.1,46.5,62.6,50.4,28.9,24.7';
my $B = '18.8,43.1,52.2,45.5,46.8,46.6,67.9,66.3,70.4,62,39.7';
my $M = "";
my $d = 33;
my $v = 0;
my @tA = split(',', $A);
my @tB = split(',', $B);
use List::Util qw(min max);
my $maxA = max @tA;
my $maxB = max @tB;
my $maxAB = ($maxA, $maxB)[$maxA < $maxB];
for(my $i = 0; $i <= $#tA; $i++){
$v = (($d/$maxA)*$tA[$i])+((($maxAB-$d)/$maxB)*$tB[$i]);
$M .= sprintf("%.2f", $v);
if($i < $#tA){$M .= ',';}
}
print($M);
# Spectral forecast for signals in Ruby
A = "10.3,23.4,44.8,63.2,44.1,35.1,46.5,62.6,50.4,28.9,24.7"
B = "18.8,43.1,52.2,45.5,46.8,46.6,67.9,66.3,70.4,62,39.7"
m = ""
tA = A.split(",")
tB = B.split(",")
maxA = tA.max.to_f
maxB = tB.max.to_f
maxAB = [maxA, maxB].max
d = 33
v = 0
for i in (0...tA.length)
v = ((d / maxA) * (tA[i].to_f)) + (((maxAB - d) / maxB) * (tB[i].to_f))
m += "#{v.round(2)}"
if i < tA.length then m += "," end
end
puts "#{m}"
// Spectral forecast for signals in Java
public class Main
{
public static void main(String[] args) {
String A = "10.3,23.4,44.8,63.2,44.1,35.1,46.5,62.6,50.4,28.9,24.7";
String B = "18.8,43.1,52.2,45.5,46.8,46.6,67.9,66.3,70.4,62,39.7";
String M = "";
String[] tA = A.split(",");
String[] tB = B.split(",");
float v = 0;
float d = 33;
float maxA = 0;
float maxB = 0;
float maxAB = 0;
for (int i = 0; i < tA.length; i++)
{
if (Float.parseFloat(tA[i]) > maxA){maxA = Float.parseFloat(tA[i]);}
if (Float.parseFloat(tB[i]) > maxB){maxB = Float.parseFloat(tB[i]);}
if (maxA > maxAB){maxAB = maxA;}
if (maxB > maxAB){maxAB = maxB;}
}
for (int i=0; i < tA.length; i++) {
v = ((d/maxA)*Float.parseFloat(tA[i]))+(((maxAB-d)/maxB)*Float.parseFloat(tB[i]));
M += Math.round(v*100)/100.0;
if(i < tA.length-1){M += ",";}
}
System.out.println(M);
}
}
// Spectral forecast for signals in JavaScript
function sf(A, B, d){
var tA = [];
var tB = [];
var M ='';
var tA = A.split(',');
var tB = B.split(',');
var maxA = Math.max.apply(null, tA);
var maxB = Math.max.apply(null, tB);
var max = Math.max(maxA, maxB);
for(var i=0; i < tA.length; i++) {
var v = ((d/maxA)*tA[i])+(((max-d)/maxB)*tB[i]);
M += v.toFixed(2);
if(i < tA.length-1){M += ','}
}
return M;
}
# Spectral forecast for signals in Python
A = "10.3,23.4,44.8,63.2,44.1,35.1,46.5,62.6,50.4,28.9,24.7"
B = "18.8,43.1,52.2,45.5,46.8,46.6,67.9,66.3,70.4,62,39.7"
M = ""
tA = list(map(float, A.split(",")))
tB = list(map(float, B.split(",")))
maxA = max(tA)
maxB = max(tB)
maxAB = max(maxA, maxB)
d = 33
for i in range(0, len(tA)):
v = ((d / maxA) * tA[i]) + (((maxAB - d) / maxB) * tB[i])
M += str(round(v,2))
if i < (len(tA) - 1): M += ","
print(M)
请注意,如果您有此处未列出的偏好,可以给我留言。根据请求,我将把代码移植到您首选的编程或脚本语言中。我不经常查看这些文章,因此请求和更新之间可能会有延迟。
题外话
据我所知,CodeProject 仍然是科学与工业之间,或者我可以说,科学家与工程师之间唯一重要的联系。因此,几年后,我决定再次在 Codeproject 上写作,但这次是用我的真名。过去某个时候,不早于 2014 年,我因在这里 Codeproject 上匿名撰写的一篇文章而获得了奖项。在 2022 年,我仍然手里拿着我的象征性奖品。
另外,我诚挚地邀请您访问我的 GitHub 帐户。在那里,您会找到许多为我的学生准备的材料,不过,也可以找到一些有趣且更高级的应用程序,这些应用程序可能对我们中某人将来可能设计的复杂项目有用。
有用链接
- 频谱预测出版物
- 信号的频谱预测方程
- 使用频谱预测进行信号处理
- 在 JS 中使用频谱预测进行波形混合
- 在 VB6 应用程序 v1.0 中使用频谱预测混合两个信号
- 在 VB6 应用程序 v2.0 中使用频谱预测混合两个信号
- 用八种编程和脚本语言组合两个信号
参考文献
- Paul A. Gagniuc 等人。《频谱预测:一种作为经典神经网络替代品的通用预测模型》。Chaos 30, 033119 (2020)
- Paul A. Gagniuc. 《生物信息学算法:理论与实现》。John Wiley & Sons, USA, 2021, ISBN: 9781119697961
历史
- 2022年3月20日:初始版本