Tôi đồng ý với những gì người khác đã nói - cụ thể là "phương sai" có thể là từ sai để sử dụng (xem như chức năng bạn đang xem xét không phải là phân phối xác suất mà là chuỗi thời gian).
Tôi nghĩ rằng bạn có thể muốn tiếp cận vấn đề này từ một góc nhìn khác - chỉ cần phù hợp với hai chuỗi thời gian với các đường cong THẤP. Bạn có thể tính toán khoảng tin cậy 95% và nhận xét định tính về hình dạng của chúng. Tôi không chắc bạn cần phải làm bất cứ điều gì lạ mắt hơn thế này.
Tôi đã viết một số mã MATLAB dưới đây để minh họa những gì tôi đang nói. Tôi đang hơi vội vàng nhưng có thể cung cấp làm rõ sớm. Phần lớn những gì tôi đã làm có thể được lấy trực tiếp từ đây: http://bloss.mathworks.com/loren/2011/01/13/data-driven-fits/
%% Generate Example data
npts = 200;
x = linspace(1,100,npts)';
y1 = (1e3*exp(-(x-25).^2/20) + 5e2*exp(-(x-65).^2/40));
y1_noisy = 50*randn(npts,1) + y1;
y2 = (1e3*exp(-(x-25).^2/60) + 5e2*exp(-(x-65).^2/100));
y2_noisy = 50*randn(npts,1) + y2;
figure; hold on
plot(x,y1_noisy,'ob')
plot(x,y2_noisy,'or')
title('raw data'); ylabel('count'); xlabel('time')
legend('y1','y2')
Bạn có thể muốn bình thường hóa hai chuỗi thời gian để so sánh các xu hướng tương đối của chúng hơn là mức tuyệt đối của chúng.
%% Normalize data sets
figure; hold on
Y1 = y1_noisy./norm(y1_noisy);
Y2 = y2_noisy./norm(y2_noisy);
plot(x,Y1,'ob')
plot(x,Y2,'or')
title('normalized data'); ylabel('normalized count'); xlabel('time')
legend('Y1','Y2')
Bây giờ làm cho THẤP phù hợp ...
%% Make figure with lowess fits
figure; hold on
plot(x,Y1,'o','Color',[0.5 0.5 1])
plot(x,Y2,'o','Color',[1 0.5 0.5])
plot(x,mylowess([x,Y1],x,0.15),'-b','LineWidth',2)
plot(x,mylowess([x,Y2],x,0.15),'-r','LineWidth',2)
title('fit data'); ylabel('normalized count'); xlabel('time')
Cuối cùng, bạn có thể tạo các dải tin cậy 95% như sau:
%% Use Bootstrapping to determine 95% confidence bands
figure; hold on
plot(x,Y1,'o','Color',[0.75 0.75 1])
plot(x,Y2,'o','Color',[1 0.75 0.75])
f = @(xy) mylowess(xy,x,0.15);
yboot_1 = bootstrp(1000,f,[x,Y1])';
yboot_2 = bootstrp(1000,f,[x,Y2])';
meanloess(:,1) = mean(yboot_1,2);
meanloess(:,2) = mean(yboot_2,2);
upper(:,1) = quantile(yboot_1,0.975,2);
upper(:,2) = quantile(yboot_2,0.975,2);
lower(:,1) = quantile(yboot_1,0.025,2);
lower(:,2) = quantile(yboot_2,0.025,2);
plot(x,meanloess(:,1),'-b','LineWidth',2);
plot(x,meanloess(:,2),'-r','LineWidth',2);
plot(x,upper(:,1),':b');
plot(x,upper(:,2),':r');
plot(x,lower(:,1),':b');
plot(x,lower(:,2),':r');
title('fit data -- with confidence bands'); ylabel('normalized count'); xlabel('time')
Bây giờ bạn có thể diễn giải con số cuối cùng như bạn muốn, và bạn có THẤP phù hợp để sao lưu giả thuyết của bạn rằng các đỉnh trong đường cong màu đỏ thực sự rộng hơn đường cong màu xanh. Nếu bạn có một ý tưởng tốt hơn về chức năng là gì, bạn có thể thực hiện hồi quy phi tuyến tính thay thế.
Chỉnh sửa: Dựa trên một số nhận xét hữu ích bên dưới, tôi sẽ thêm một số chi tiết khác về việc ước tính độ rộng cực đại một cách rõ ràng. Trước tiên, bạn cần đưa ra một số định nghĩa cho những gì bạn đang xem là "đỉnh" ở vị trí đầu tiên. Có lẽ bất kỳ vết sưng nào tăng quá ngưỡng (khoảng 0,05 trong các ô tôi đã thực hiện ở trên). Nguyên tắc cơ bản là bạn nên tìm cách tách các đỉnh "thực" hoặc "đáng chú ý" khỏi nhiễu.
Sau đó, với mỗi đỉnh, bạn có thể đo chiều rộng của nó theo một vài cách. Như tôi đã đề cập trong các bình luận bên dưới, tôi nghĩ thật hợp lý khi xem xét "nửa chiều rộng tối đa" nhưng bạn cũng có thể nhìn vào tổng thời gian đỉnh vượt quá ngưỡng của bạn. Tốt nhất, bạn nên sử dụng một số biện pháp khác nhau về chiều rộng cực đại và báo cáo mức độ phù hợp của kết quả của bạn đối với các lựa chọn này.
Bất kể số liệu nào bạn chọn, bạn có thể sử dụng bootstrapping để tính khoảng tin cậy cho mỗi đỉnh trong mỗi dấu vết.
f = @(xy) mylowess(xy,x,0.15);
N_boot = 1000;
yboot_1 = bootstrp(N_boot,f,[x,Y1])';
yboot_2 = bootstrp(N_boot,f,[x,Y2])';
Mã này tạo ra 1000 bootstrapping phù hợp cho các dấu vết màu xanh và đỏ trong các ô ở trên. Một chi tiết mà tôi sẽ đề cập đến là sự lựa chọn hệ số làm mịn 0.15 - bạn có thể chọn tham số này để nó giảm thiểu lỗi xác thực chéo (xem liên kết tôi đã đăng). Bây giờ tất cả những gì bạn phải làm là viết một hàm cô lập các đỉnh và ước tính độ rộng của chúng:
function [t_peaks,heights,widths] = getPeaks(t,Y)
%% Computes a list of times, heights, and widths, for each peak in a time series Y
%% (column vector) with associated time points t (column vector).
% The implementation of this function will be problem-specific...
Sau đó, bạn chạy mã này trên 1000 đường cong cho mỗi tập dữ liệu và tính phần trăm thứ 2,5 và 97,5 cho chiều rộng của mỗi đỉnh. Tôi sẽ minh họa điều này trên chuỗi thời gian Y1 - bạn sẽ làm tương tự cho chuỗi thời gian Y2 hoặc bất kỳ tập hợp dữ liệu quan tâm nào khác.
N_peaks = 2; % two peaks in example data
t_peaks = nan(N_boot,N_peaks);
heights = nan(N_boot,N_peaks);
widths = nan(N_boot,N_peaks);
for aa = 1:N_boot
[t_peaks(aa,:),heights(aa,:),widths(aa,:)] = getPeaks(x,yboot_1(:,aa));
end
quantile(widths(:,1),[0.025 0.975]) % confidence interval for the width of first peak
quantile(widths(:,2),[0.025 0.975]) % same for second peak width
Nếu bạn mong muốn, bạn có thể thực hiện các bài kiểm tra giả thuyết thay vì tính khoảng tin cậy. Lưu ý rằng mã ở trên là đơn giản - nó giả sử mỗi đường cong thấp được khởi động sẽ có 2 đỉnh. Giả định này có thể không luôn luôn giữ, vì vậy hãy cẩn thận. Tôi chỉ đang cố gắng minh họa cách tiếp cận mà tôi sẽ thực hiện.
Lưu ý: chức năng "mylowess" được đưa ra trong liên kết tôi đã đăng ở trên. Đây là những gì nó trông giống như ...
function ys=mylowess(xy,xs,span)
%MYLOWESS Lowess smoothing, preserving x values
% YS=MYLOWESS(XY,XS) returns the smoothed version of the x/y data in the
% two-column matrix XY, but evaluates the smooth at XS and returns the
% smoothed values in YS. Any values outside the range of XY are taken to
% be equal to the closest values.
if nargin<3 || isempty(span)
span = .3;
end
% Sort and get smoothed version of xy data
xy = sortrows(xy);
x1 = xy(:,1);
y1 = xy(:,2);
ys1 = smooth(x1,y1,span,'loess');
% Remove repeats so we can interpolate
t = diff(x1)==0;
x1(t)=[]; ys1(t) = [];
% Interpolate to evaluate this at the xs values
ys = interp1(x1,ys1,xs,'linear',NaN);
% Some of the original points may have x values outside the range of the
% resampled data. Those are now NaN because we could not interpolate them.
% Replace NaN by the closest smoothed value. This amounts to extending the
% smooth curve using a horizontal line.
if any(isnan(ys))
ys(xs<x1(1)) = ys1(1);
ys(xs>x1(end)) = ys1(end);
end