อัลกอริทึมในการสุ่มตัวอย่างใหม่จากอัตราตัวแปรเป็นอัตราคงที่คืออะไร


27

ฉันมีเซ็นเซอร์ที่รายงานการอ่านด้วยการประทับเวลาและค่า อย่างไรก็ตามจะไม่สร้างการอ่านในอัตราคงที่

ฉันพบว่าข้อมูลอัตราตัวแปรนั้นยากที่จะจัดการ ตัวกรองส่วนใหญ่คาดว่าอัตราตัวอย่างคงที่ กราฟการวาดง่ายขึ้นด้วยอัตราตัวอย่างคงที่เช่นกัน

มีอัลกอริธึมที่จะสุ่มตัวอย่างจากอัตราตัวอย่างแปรไปเป็นอัตราตัวอย่างคงที่หรือไม่?


นี่คือข้ามโพสต์จากโปรแกรมเมอร์ ฉันบอกว่านี่เป็นสถานที่ที่ดีกว่าที่จะถาม programmers.stackexchange.com/questions/193795/…
FigBug

สิ่งที่กำหนดเมื่อเซ็นเซอร์จะรายงานการอ่าน? มันส่งการอ่านเฉพาะเมื่อการอ่านเปลี่ยนไปหรือไม่ วิธีง่าย ๆ คือเลือก "ช่วงเวลาตัวอย่างเสมือน" (T) ที่เล็กกว่าเวลาที่สั้นที่สุดระหว่างการอ่านที่สร้างขึ้น ที่อินพุตอัลกอริทึมเก็บเฉพาะการอ่านรายงานล่าสุด (CurrentReading) ที่เอาต์พุตอัลกอริทึมรายงาน CurrentReading เป็น“ ตัวอย่างใหม่” ทุก T วินาทีเพื่อให้บริการตัวกรองหรือกราฟได้รับการอ่านในอัตราคงที่ (ทุก T วินาที) ไม่มีความคิดว่านี่จะเพียงพอในกรณีของคุณ
2718

มันพยายามที่จะสุ่มตัวอย่างทุก 5ms หรือ 10ms แต่มันเป็นงานที่มีลำดับความสำคัญต่ำดังนั้นจึงอาจพลาดหรือล่าช้า ฉันมีเวลาที่แม่นยำถึง 1 มิลลิวินาที การประมวลผลนั้นทำบนพีซีไม่ใช่แบบเรียลไทม์ดังนั้นอัลกอริธึมที่ช้าก็โอเคถ้าทำได้ง่ายกว่า
FigBug

1
คุณได้ดูการฟื้นฟูฟูริเยร์หรือไม่? มีการแปลงฟูเรียร์ตามข้อมูลตัวอย่างที่ไม่สม่ำเสมอ aoproach ปกติคือการแปลงภาพฟูริเยร์กลับไปยังโดเมนเวลาตัวอย่างที่เท่าเทียมกัน
mbaitoff

3
คุณรู้ลักษณะของสัญญาณพื้นฐานที่คุณกำลังสุ่มตัวอย่างหรือไม่? หากข้อมูลที่เว้นระยะแบบผิดปกติยังคงอยู่ในอัตราตัวอย่างที่สูงพอสมควรเมื่อเทียบกับแบนด์วิดท์ของสัญญาณที่ถูกวัดดังนั้นสิ่งที่ง่ายเช่นการแก้ไขพหุนามกับตารางเวลาที่เท่ากันอาจทำงานได้ดี
Jason R

คำตอบ:


21

วิธีที่ง่ายที่สุดคือการแก้ไขแบบอิสระเช่นJim Clay แนะนำ (เชิงเส้นหรืออื่น ๆ ) อย่างไรก็ตามหากคุณมีความหรูหราของการประมวลผลแบบแบทช์และโดยเฉพาะอย่างยิ่งถ้าคุณมีตัวอย่างที่ไม่ได้กำหนดจำนวนมากเกินไปมันมีอัลกอริทึม "การสร้างใหม่ที่สมบูรณ์แบบ" ซึ่งสง่างามที่สุด สำหรับเหตุผลที่เป็นตัวเลขอาจไม่สามารถใช้ได้ในทุกกรณี แต่อย่างน้อยก็ควรรู้เกี่ยวกับแนวคิด ก่อนอื่นฉันอ่านเกี่ยวกับเรื่องนี้ในเอกสารนี้

เคล็ดลับคือการพิจารณากลุ่มตัวอย่าง nonuniform ของคุณว่ามีการสร้างขึ้นใหม่จากตัวอย่างสม่ำเสมอผ่านการแก้ไขแบบซิน ตามสัญลักษณ์ในกระดาษ:

y(t)=k=1Ny(kT)sin(π(tkT)/T)π(tkT)/T=k=1Ny(kT)sinc(tkTT).

โปรดทราบว่านี่เป็นชุดของสมการเชิงเส้นหนึ่งชุดสำหรับแต่ละตัวอย่างที่ไม่ใช่แบบฟอร์มโดยที่ไม่ทราบค่าเป็นตัวอย่างระยะห่างเท่ากันเช่น:y ( k T )y(t)y(kT)

[y(t0)y(t1)y(tm)]=[sinc(t0TT)sinc(t02TT)sinc(t0nTT)sinc(t1TT)sinc(t12TT)sinc(t1nTT)sinc(tmTT)sinc(tm2TT)sinc(tmnTT)][y(T)y(2T)y(nT)].

ในสมการข้างต้นคือจำนวนตัวอย่างเครื่องแบบที่ไม่รู้จักคือค่าผกผันของอัตราตัวอย่างสม่ำเสมอและคือจำนวนตัวอย่างที่ไม่เป็นรูปแบบ (ซึ่งอาจมากกว่า ) ด้วยการคำนวณวิธีกำลังสองน้อยที่สุดของระบบนั้นจะสามารถสร้างตัวอย่างแบบสม่ำเสมอได้ ในทางเทคนิคเท่านั้นตัวอย่างสม่ำเสมอเป็นสิ่งจำเป็น แต่ขึ้นอยู่กับวิธีการ "กระจัดกระจาย" พวกเขาอยู่ในเวลาเมทริกซ์การแก้ไขอาจจะน่ากลัวป่วยปรับอากาศ เมื่อเป็นเช่นนั้นการใช้ตัวอย่างที่ไม่ได้เป็นรูปแบบปกติจะช่วยได้มากขึ้นT m n nnTmnn

เป็นตัวอย่างของเล่นต่อไปนี้เป็นการเปรียบเทียบ (โดยใช้numpy ) ระหว่างวิธีการข้างบนและการแก้ไขลูกบาศก์ spline บนตารางที่มีการสั่นเล็กน้อย:

Sinc vs การสร้าง Spline ลูกบาศก์ของตัวอย่าง Nonuniform

(รหัสในการทำซ้ำพล็อตข้างต้นรวมอยู่ในตอนท้ายของคำตอบนี้)

ทั้งหมดที่กล่าวมาสำหรับวิธีการที่มีคุณภาพสูงและมีประสิทธิภาพเริ่มต้นด้วยบางสิ่งในเอกสารใดเอกสารหนึ่งต่อไปนี้อาจจะเหมาะสมกว่า:

A. Aldroubi และ Karlheinz Grochenig การสุ่มตัวอย่าง Nonuniform และการสร้างใหม่ในช่องว่าง shift-invariant , SIAM Rev. , 2001, no. 4, 585-620 ( ลิงก์ pdf )

K. Grochenig และ H. Schwab, วิธีการสร้างใหม่แบบเร็วสำหรับการสุ่มตัวอย่างแบบไม่สม่ำเสมอในช่องว่าง shift-invariant , SIAM J. Matrix Anal Appl., 24 (2003), 899- 913

-

import numpy as np
import pylab as py

import scipy.interpolate as spi
import numpy.random as npr
import numpy.linalg as npl

npr.seed(0)

class Signal(object):

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def plot(self, title):
        self._plot(title)
        py.plot(self.x, self.y ,'bo-')
        py.ylim([-1.8,1.8])
        py.plot(hires.x,hires.y, 'k-', alpha=.5)

    def _plot(self, title):
        py.grid()
        py.title(title)
        py.xlim([0.0,1.0])

    def sinc_resample(self, xnew):
        m,n = (len(self.x), len(xnew))
        T = 1./n
        A = np.zeros((m,n))

        for i in range(0,m):
            A[i,:] = np.sinc((self.x[i] - xnew)/T)

        return Signal(xnew, npl.lstsq(A,self.y)[0])

    def spline_resample(self, xnew):
        s = spi.splrep(self.x, self.y)
        return Signal(xnew, spi.splev(xnew, s))

class Error(Signal):

    def __init__(self, a, b):
        self.x = a.x
        self.y = np.abs(a.y - b.y)

    def plot(self, title):
        self._plot(title)
        py.plot(self.x, self.y, 'bo-')
        py.ylim([0.0,.5])

def grid(n): return np.linspace(0.0,1.0,n)
def sample(f, x): return Signal(x, f(x))

def random_offsets(n, amt=.5):
    return (amt/n) * (npr.random(n) - .5)

def jittered_grid(n, amt=.5):
    return np.sort(grid(n) + random_offsets(n,amt))

def f(x):
    t = np.pi * 2.0 * x
    return np.sin(t) + .5 * np.sin(14.0*t)

n = 30
m = n + 1

# Signals
even   = sample(f, np.r_[1:n+1] / float(n))
uneven = sample(f, jittered_grid(m))
hires  = sample(f, grid(10*n))

sinc   = uneven.sinc_resample(even.x)
spline = uneven.spline_resample(even.x)

sinc_err   = Error(sinc, even)
spline_err = Error(spline, even)

# Plot Labels
sn = lambda x,n: "%sly Sampled (%s points)" % (x,n)
r  = lambda x: "%s Reconstruction" % x
re = lambda x: "%s Error" % r(x)

plots = [
    [even,       sn("Even", n)],
    [uneven,     sn("Uneven", m)],
    [sinc,       r("Sinc")],
    [sinc_err,   re("Sinc")],
    [spline,     r("Cubic Spline")],
    [spline_err, re("Cubic Spline")]
]

for i in range(0,len(plots)):
    py.subplot(3, 2, i+1)
    p = plots[i]
    p[0].plot(p[1])

py.show()

วิธีการที่ดีและรหัส แต่สำหรับโดยมีเล็กน้อย (เช่น [0 1 - 3 4 5 - 7 8] T) ซึ่งฉันคิดว่าเป็นคำถาม OPs ไม่ใช่ sinc ในเมทริกซ์ทั้งหมดใช่ไหม แน่นอนว่ามีวิธีการแก้ไข แต่ tj=jT
เดนิส

ตามที่ฉันเข้าใจแล้วคำถามของ OP นั้นเกี่ยวกับตัวอย่างที่หลุดและ / หรือล่าช้า โดยทั่วไปวิธีการนี้เป็นเพียงระบบสมการ overdetermined ดังนั้นตัวอย่างที่ถูกปล่อยจะแสดงเป็นไม่ทราบ (ไม่เป็นจุดข้อมูลที่มีค่าเป็น 0) หรืออาจไม่ใช่สิ่งที่คุณถาม
เก็บข้อมูล

จะเกิดอะไรขึ้นถ้าเป็นจำนวนเต็มทั้งหมด (T = 1) สมมติว่าเรามีจุดข้อมูล [ ] สำหรับชุดของเลขจำนวนเต็มที่ไม่เป็นศูนย์เช่น {-1 1} หรือ {-2 -1 1 2}; ไม่ใช่การสอดแทรกไม่ว่า - หรือฉันพลาดอะไรไป j , y j j J y 0 = 0 y jtjj,yjjJy0=0yj
ปฏิเสธ

หากอัตราตัวอย่างเหมือนกันอย่างแน่นอน (w / จุดขาดหายไป) เมทริกซ์การแก้ไขจะกระจัดกระจาย (เพราะแต่ละเอาต์พุตขึ้นอยู่กับอินพุตเดียวเท่านั้น) โดยทั่วไปอัตราตัวอย่างเฉลี่ยของตัวอย่างที่ไม่ได้อยู่ในรูปแบบจำเป็นต้องมากกว่าอัตราการสร้างใหม่ที่สม่ำเสมอ กล่าวอีกนัยหนึ่งคุณจะต้องสร้างใหม่ในอัตราที่ต่ำกว่าเพื่อ "เติมช่องว่าง" (T> 1 สำหรับตัวอย่างของคุณ) ฉันเห็นประเด็นของคุณแล้ว
นัก

2
คำตอบเช่นนี้เป็นทองคำบริสุทธิ์
Ahmed Fasih

6

ดูเหมือนว่าปัญหาของการแปลงอัตราตัวอย่างแบบอะซิงโครนัส ในการแปลงจากอัตราตัวอย่างหนึ่งไปเป็นอัตราอื่นเราสามารถคำนวณการแสดงสัญญาณต่อเนื่องของเวลาโดยดำเนินการแก้ไขแบบ sinc จากนั้นทำการสุ่มที่อัตราตัวอย่างใหม่ของเรา สิ่งที่คุณกำลังทำไม่แตกต่างกันมาก คุณต้องสุ่มสัญญาณของคุณใหม่เพื่อให้มีเวลาตัวอย่างที่ได้รับการแก้ไข

สัญญาณเวลาต่อเนื่องสามารถคำนวณได้โดยการชักตัวอย่างแต่ละตัวอย่างด้วยฟังก์ชัน sinc เนื่องจากฟังก์ชั่น sinc ยังคงดำเนินต่อไปเรื่อย ๆ เราจึงใช้สิ่งที่มีประโยชน์มากกว่าเช่น sinc แบบหน้าต่างที่มีความยาวแน่นอน ส่วนที่ยุ่งยากคือเนื่องจากตัวอย่างของคุณเคลื่อนที่ไปตามกาลเวลาอาจต้องใช้ซินที่มีเฟสออฟเซ็ตต่างกันสำหรับแต่ละตัวอย่างเมื่อทำการสุ่มใหม่

สัญญาณเวลาต่อเนื่องจากสัญญาณตัวอย่าง:

x(t)=n=x[n]sinc(tnTsTs)

ที่คือเวลาตัวอย่างของคุณ อย่างไรก็ตามในกรณีของคุณเวลาตัวอย่างของคุณจะไม่คงที่ ดังนั้นฉันคิดว่าคุณต้องแทนที่ด้วยเวลาตัวอย่างในตัวอย่างนั้นTs

x(t)=n=x[n]sinc(tnTs[n]Ts[n])

จากนี้คุณสามารถสุ่มสัญญาณได้ใหม่:

y[n]=x(nTns )

โดยที่คือเวลาตัวอย่างที่ต้องการTns

นำทุกอย่างมารวมกันคุณจะได้รับ:

y[m]=n=x[n]sinc(mTnsnTs[n]Ts[n])

เนื่องจากสิ่งนี้ไม่ได้เป็นสาเหตุหรือเวไนยฟังก์ชัน sinc สามารถถูกแทนที่ด้วยฟังก์ชันของการสนับสนุน จำกัด และขอบเขตของการรวมปรับตาม

ให้เคอร์เนล (t) เป็น sinc แบบเรียงหน้าต่างหรือฟังก์ชันอื่น ๆ ที่มีความยาว 2k คล้ายกัน:

y[m]=n=kkx[n]kernel(mTnsnTs[n]Ts[n])

ฉันหวังว่าสิ่งนี้จะช่วย ... แต่ฉันอาจทำผิดไปตลอดทางและอาจเป็นวิชาคณิตศาสตร์เล็กน้อย ฉันอยากจะแนะนำการวิจัยการแปลงอัตราตัวอย่างสำหรับข้อมูลเพิ่มเติม บางทีคนอื่นที่นี่อาจให้คำอธิบายที่ดีกว่า


การใช้ฟังก์ชั่น sinc เพื่อสร้างสัญญาณรุ่นต่อเนื่องจำเป็นต้องให้เว้นระยะตัวอย่างเท่ากันดังนั้นฟังก์ชัน sinc จะต้องปรับให้เข้ากับระยะห่างตัวอย่างตัวอย่าง อาจนำไปใช้ค่อนข้างยาก
user2718

ใช่มันจะไม่มีประสิทธิภาพมากที่จะทำอย่างที่เห็นในที่นี้ มันจะต้องมีการคำนวณค่าสัมประสิทธิ์เคอร์เนลใหม่สำหรับแต่ละตัวอย่างเวลาที่แตกต่างกัน การสะสมของเมล็ดข้าวหลายชนิดสามารถคำนวณได้และเวลาที่วัดได้จากหนึ่งในเหล่านี้ จะมีการเข้าชมประสิทธิภาพเทียบกับข้อผิดพลาดการแปลงเป็นจำนวนมาก
จาค็อบ

คุณสามารถคำนวณตารางการค้นหา sinc ล่วงหน้าและแก้ไขระหว่างจุดของตารางการค้นหานั้นล่วงหน้า
jms

5

ฉันคิดว่าคำตอบของยาโคบทำได้ดีมาก

วิธีที่ง่ายกว่าซึ่งอาจไม่ดีเท่าที่ควรในการแนะนำการบิดเบือนคือการแก้ไขพหุนาม ฉันจะใช้การประมาณเชิงเส้น (ง่ายไม่ดีเท่าประสิทธิภาพสัญญาณที่ชาญฉลาด) หรือลูกบาศก์ splines (ยังไม่ยากเกินไปประสิทธิภาพสัญญาณดีกว่า) เพื่อสร้างตัวอย่างในเวลาใดก็ได้ที่คุณต้องการจากตัวอย่างเวลาโดยพลการของคุณ


1
คำตอบของคุณดูเหมือนจะง่ายกว่าการติดตั้งของจาค็อบดังนั้นฉันจึงไปกับมันก่อน ดูเหมือนว่าจะใช้งานได้ แต่ฉันยังไม่ได้ทำการทดสอบครบชุด
FigBug

1
@FigBug - หากคุณมีเวลาเพิ่มความคิดเห็นกับคุณเป็นทางออกสุดท้าย
user2718

2

(หนึ่งเดือนต่อมา) มีสองตัวเลือกหลักสำหรับวิธีการแก้ไขใด ๆ :
1) จำนวนจุดข้อมูลที่ใกล้ที่สุดกับจุดที่หายไปที่จะใช้ไม่ 2 4 6 ... 2) ชั้นของฟังก์ชั่นพื้นฐานที่จะใช้: เชิงเส้นพหุนาม ไซน์ - โคไซน์ (ฟูริเยร์), คิวบิกคิวรี่ (B-spline หรือ interpolating spline), sinc-like ... (ตัวเลือก 0 คือว่าจะใช้วิธีการและรหัสของคนอื่นหรือทำมันด้วยตัวเอง)Nnear

ฟิตติ้งเป็นเส้นตรงไปจุดเป็นเรื่องง่าย: 2 จุด [-1, ], [1 ]:ประเมิน จุดมีค่าเฉลี่ย :ค่าเฉลี่ย ทั่วไป :ดูเช่น สูตรคำนวณตัวเลข p 781: พอดีบรรทัด และประเมินซิม One สามารถใส่ quadratics, cubics, sine-cosines ได้ในลักษณะเดียวกันY - 1ปี1Nnear
y1y1
[ x i , y i ] x i = 0y0(y1+y1)/2
[xi,yi]xi=0
y i [ x i , y i ]y0yi
[xi,yi]
y 0aa+bxy0a

ฉันเข้าใจว่าคุณมีข้อมูลที่เว้นระยะเท่ากันโดยมีจุดขาดหายไปสองสามข้อใช่ไหม?
การแก้ไขเชิงเส้นทำงานได้ดีแค่ไหนสำหรับกรณีนี้
ทีนี้ลอง cosกับ = 0.25: 1 0 -1 0 1 0 -1 0 ... 2 เพื่อนบ้านของจุดเฉลี่ยใด ๆ ถึง 0, แย่มาก 4 เพื่อนบ้าน: ค่าเฉลี่ยของ [1 0 (ขาด -1) 0 1] = 1/2, แย่มาก (ลองใช้ตัวกรอง 4 เพื่อนบ้าน [-1 3 3 -1] / 4 ในเรื่องนี้)f2πftf


การรวมเชิงเส้นตรงกับ 4 หรือ 6 หรือ 8 เพื่อนบ้านอาจทำงานได้ดีพอสำหรับข้อมูลของคุณ
ฉันขอแนะนำให้เริ่มต้นด้วยวิธีการที่คุณเข้าใจอย่างถี่ถ้วนก่อนที่จะดำดิ่งลงไปในแนวโค้งเหมือนคนงี่เง่า ...


อีกวิธีการที่แตกต่างกันค่อนข้าง ผกผันน้ำหนักระยะ มันง่ายที่จะใช้งาน (ดูidw-interpolation-with-pythonบน SO), ทำงานใน 2d 3d ขึ้นไปเช่นกัน แต่มันยากที่จะวิเคราะห์ตามหลักวิชา

(เห็นได้ชัดว่าไม่มีวิธีการแก้ไขเพียงครั้งเดียวอาจพอดี zillions ของการรวมกันของ
[สัญญาณเสียงตัวชี้วัดข้อผิดพลาดฟังก์ชั่นการทดสอบ] ที่เกิดขึ้นในความเป็นจริง.
มีวิธีการอื่น ๆ ในโลกโดยมีลูกบิดมากขึ้นกว่าฟังก์ชั่นการทดสอบ.
อย่างไรก็ตามแกลเลอรี่ วิธีการและฟังก์ชั่นทดสอบอาจมีประโยชน์)


1

หากคุณทำงานกับ matlab คุณสามารถทำได้โดยทำงานกับ timeseries

time  % is your starting vector of time

data % vector of data you want to resample 

data_TS = timeseries(data,time); % define the data as a timeseries 

new_time = time(0):dt:time(end); % new vector of time with fixed dt=1/fs

data_res = resample(data_TS,new_time); % data resampled at constant fs

0

ก่อนที่คุณจะทำการประมวลผลที่แปลกใหม่คุณสามารถลองอะไรแบบนี้ได้ง่าย ๆ (โค้ดหลอก - ไม่มีการแก้ไข แต่สามารถเพิ่มได้)

TimeStamp[]  //Array of Sensor TimeStamps -NULL terminated – TimeStamp[i] corresponds to Reading[i]
Reading[]      //Array of Sensor Readings       -NULL terminated

AlgorithmOut   //Delimited file of of readings in fixed sample time (5ms) 
CurrentSavedReading = Reading[0]

SampleTime=TimeStamp[0] //ms virtual sample time, 5ms fixed samples

i = 0 // loop index
While(TimeStamp[i] != NULL)
{
   FileWrite (CurrentSavedReading, AlgorithmOut)//write value to file
   SampleTime = SampleTime + 5//ms
   if(SampleTime > TimeStamp[i])
   {
      i++
      CurrentSavedReading = Reading[i]
   }
}

0

คำตอบของ IMHO Datageist นั้นถูกต้องคำตอบของ Jacob นั้นไม่ถูกต้อง วิธีง่ายๆในการตรวจสอบสิ่งนี้คืออัลกอริทึมที่แนะนำของนักข้อมูลรับประกันว่าจะสอดแทรกผ่านตัวอย่างดั้งเดิม (สมมติว่าความแม่นยำเชิงตัวเลขที่ไม่มีที่สิ้นสุด) ในขณะที่คำตอบของจาค็อบไม่ได้

  • สำหรับกรณีการสุ่มตัวอย่างที่เหมือนกันชุดของฟังก์ชัน sinc คือ orthogonal: ถ้าฟังก์ชัน sinc ที่เลื่อนแต่ละหน่วยถูกแยกออกจากตัวอย่างอินพุตพวกมันจะกลายเป็นเมทริกซ์เอกลักษณ์ที่ไม่มีที่สิ้นสุด นี่เป็นเพราะบาป (n pi) / (n pi) เป็นศูนย์สำหรับ n ทั้งหมดยกเว้น n = 0
  • อย่างไรก็ตามคุณสมบัตินี้ไม่สามารถคาดการณ์ได้ในกรณีที่ไม่เหมือนกัน: ชุดฟังก์ชัน sinc ที่คล้ายกันซึ่งแยกส่วนไปจากตัวอย่างอินพุตจะให้เมทริกซ์ที่ไม่น่าสนใจ ดังนั้นการมีส่วนร่วมจากตัวอย่างรอบข้างจะไม่เป็นศูนย์และการสร้างใหม่จะไม่สอดแทรกเข้าไปในตัวอย่างอินพุตอีกต่อไป
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.