自相关实操流程
假设我有一个信号: [1,1,1,1,1,3,3,2,2,2,2,4,1,2,4,2,1,1,1]
1、求信号的均值(可以先归一化)
avg = 1.8947
2、计算均方差
(1-1.8947)平方
(1-1.8947)平方
(1-1.8947)平方
(1-1.8947)平方
(1-1.8947)平方
(3-1.8947)平方
(3-1.8947)平方
(2-1.8947)平方
(2-1.8947)平方
(2-1.8947)平方
(2-1.8947)平方
(4-1.8947)平方
(1-1.8947)平方
(2-1.8947)平方
(4-1.8947)平方
(2-1.8947)平方
(1-1.847)平方
(1-1.8947)平方
(1-1.8947)平方
其结果为:
各点与均值的偏差: ['-0.895', '-0.895', '-0.895', '-0.895', '-0.895', '1.105', '1.105', '0.105', '0.105', '0.105', '0.105', '2.105', '-0.895', '0.105', '2.105', '0.105', '-0.895', '-0.895', '-0.895'] 分母 = Σ(x[i]-μ)² = 20.8421
3、计算延迟k=1的协方差
i= 0: (1-1.895)×(1-1.895) = -0.895×-0.895 = 0.801 i= 1: (1-1.895)×(1-1.895) = -0.895×-0.895 = 0.801 i= 2: (1-1.895)×(1-1.895) = -0.895×-0.895 = 0.801 i= 3: (1-1.895)×(3-1.895) = -0.895×1.105 = -0.989 i= 4: (3-1.895)×(3-1.895) = 1.105×1.105 = 1.221 i= 5: (3-1.895)×(2-1.895) = 1.105×0.105 = 0.116 i= 6: (2-1.895)×(2-1.895) = 0.105×0.105 = 0.011 i= 7: (2-1.895)×(2-1.895) = 0.105×0.105 = 0.011 i= 8: (2-1.895)×(2-1.895) = 0.105×0.105 = 0.011 i= 9: (2-1.895)×(4-1.895) = 0.105×2.105 = 0.221 i=10: (4-1.895)×(1-1.895) = 2.105×-0.895 = -1.884 i=11: (1-1.895)×(2-1.895) = -0.895×0.105 = -0.094 i=12: (2-1.895)×(4-1.895) = 0.105×2.105 = 0.221 i=13: (4-1.895)×(2-1.895) = 2.105×0.105 = 0.221 i=14: (2-1.895)×(1-1.895) = 0.105×-0.895 = -0.094 i=15: (1-1.895)×(1-1.895) = -0.895×-0.895 = 0.801 i=16: (1-1.895)×(1-1.895) = -0.895×-0.895 = 0.801 i=17: (1-1.895)×(1-1.895) = -0.895×-0.895 = 0.801分子 = Σ(x[i]-μ)(x[i+1]-μ) = 15.0263
4、最终计算自相关的值
延迟1自相关 R[1] = 分子/分母 = 15.0263 / 20.8421 = 0.721
直观理解
这个0.721的值意味着:
当延迟为1时,信号与其自身有72.1%的相似性
这很高,说明相邻数据点之间有很强的相关性
在信号A中,你经常看到
1,1、2,2、3,3这样的连续相同值,这导致了高自相关
JAVA编程实现:
package model.MyTools;import testHtt.SystemTools;import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;public class TestCorrecation {/*** PPG信号检测方法* 主要通过自相关函数来判别是否可以对同一个信号进行周期的判断* author:huitao* time:2025-11-13* @param single* @return*///自相关函数的编程(true表示高度相关,false表示不相关)public static boolean CorrelationTools(List<Double> single){double lat=0;//取平均值double avg= SystemTools.getAvagetValue(single);//求差值List<Double> offsetList= new ArrayList<>();double offsetResult=0;for(int i=0;i<single.size();i++){double offset=single.get(i)-avg;offsetList.add(offset);offsetResult += offset*offset; //计算平方}offsetResult = offsetResult/single.size();//0位置的相关系数String formattedNumber = String.format("%.1f", offsetResult);System.out.print(formattedNumber+"\n");//计算延迟1的相关//打点器1List<Double> nList=getNListValue(single,20);double point1=0;//获取位置1的点的关系for(int j=0;j<single.size();j++){double x1=single.get(j);double x2=nList.get(j);double NValue=(x1-avg)*(x2-avg);point1 += NValue;}point1 = point1/single.size();System.out.print(point1+"\n");//获取最终自相关系数的关系double ResultCorrelation=point1/offsetResult;String formattedNumber1 = String.format("%.1f", ResultCorrelation);System.out.print(formattedNumber1+"\n");boolean flag=false;if(ResultCorrelation>=0.3){flag=true;}return flag;}//获取具体位置的对比关系public static List<Double> getNListValue(List<Double> llopp,int index){List<Double> nList1=new ArrayList();List<Double> nList2=new ArrayList();List<Double> result=new ArrayList();for(int k=0;k<llopp.size();k++){if(k>index){nList2.add(llopp.get(k));//开始}else{nList1.add(llopp.get(k));//结束}}result.addAll(nList2);result.addAll(nList1);return result;}//通过文件读取数据private static List<Double> readFile(String path) {List<Double> ll=new ArrayList<>();String line="";try{BufferedReader in=new BufferedReader(new FileReader(path));while ((line=in.readLine()) != null){//表示字符串长度不受限制
// String[] str=line.split(" ",-1);//先把外面的替换掉String c = line.replaceAll("\r|\n", "");String[] str=c.split(" ");for(int i=0;i<str.length;i++){if (i % 5 == 0 || i % 5 == 1 || i % 5 == 2) {double dat = Double.parseDouble(str[i]);
// System.out.print(dat+"\n");ll.add(dat);}}}in.close();} catch (IOException e) {e.printStackTrace();}System.out.print(ll.size());return ll;}public static void main(String[] args){String path="C:\\Users\\seer\\Desktop\\王总错误数据\\bbbbb.txt";
// String path="C:\\Users\\seer\\Desktop\\王总错误数据\\2025-08-06 103859\\a7c9bff53f2e4a70af7a9f641552507a_1754447849073-35.txt";
// String path="C:\\Users\\seer\\Desktop\\测量无效\\vlide\\error2.txt";List<Double> lp=readFile(path);boolean fg=CorrelationTools(lp);System.out.print(fg);}}
