ห้องสมุดสำหรับระยะทางอนุกรมเวลา (เช่น การแปรปรวนเวลาแบบไดนามิก) ที่ใช้ในกลุ่มวิจัย DTAI ไลบรารีนำเสนอการใช้งาน Python อย่างแท้จริงและการใช้งานที่รวดเร็วใน C การใช้งาน C มีเพียง Cython เท่านั้นที่ขึ้นต่อกัน มันเข้ากันได้กับ Numpy และ Pandas และนำไปใช้เพื่อหลีกเลี่ยงการคัดลอกข้อมูลที่ไม่จำเป็น
เอกสารประกอบ: http://dtaidistance.readthedocs.io
ตัวอย่าง:
from dtaidistance import dtw
import numpy as np
s1 = np.array([0.0, 0, 1, 2, 1, 0, 1, 0, 0])
s2 = np.array([0.0, 1, 2, 0, 0, 0, 0, 0, 0])
d = dtw.distance_fast(s1, s2)
อ้างถึงงานนี้:
วานเนส เมียร์ต, คิลเลียน เฮนดริกซ์, ตูน แวน เครเนนดอนค์, ปีเตอร์ ร็อบเบเรชท์ส, เฮนดริก บล็อกคีล และเจสซี่ เดวิส
DTAIDistance (เวอร์ชัน v2) เซโนโด
http://doi.org/10.5281/zenodo.5901139
ใหม่ใน v2 :
ssize_t
แทน int
อย่างต่อเนื่องทำให้โครงสร้างข้อมูลมีขนาดใหญ่ขึ้นบนเครื่อง 64 บิต และเข้ากันได้กับ Numpy มากขึ้นmax_dist
กลายเป็นคล้ายกับงานของ Silva และ Batista ใน PrunedDTW [7] กล่องเครื่องมือใช้เวอร์ชันที่เท่ากับ PrunedDTW เนื่องจากจะตัดระยะทางบางส่วนมากขึ้น นอกจากนี้ อาร์กิวเมนต์ use_pruning
จะถูกเพิ่มเพื่อตั้ง max_dist
เป็นระยะทางแบบยุคลิดโดยอัตโนมัติ ตามที่ Silva และ Batista แนะนำ เพื่อเพิ่มความเร็วในการคำนวณ (มีวิธีใหม่ ub_euclidean
)dtaidistance.dtw_ndim
$ pip install dtaidistance
หรือ
$ conda install -c conda-forge dtaidistance
การติดตั้ง pip ต้องใช้ Numpy เป็นการพึ่งพาในการรวบรวมโค้ด C ที่เข้ากันได้กับ Numpy (โดยใช้ Cython) อย่างไรก็ตาม การขึ้นต่อกันนี้เป็นทางเลือกและสามารถลบออกได้
ดูซอร์สโค้ดได้ที่ github.com/wannesm/dtaidistance
หากคุณพบปัญหาใดๆ ในระหว่างการคอมไพล์ (เช่น การใช้งานแบบ C หรือ OpenMP ไม่พร้อมใช้งาน) โปรดดูตัวเลือกเพิ่มเติมในเอกสารประกอบ
from dtaidistance import dtw
from dtaidistance import dtw_visualisation as dtwvis
import numpy as np
s1 = np.array([0., 0, 1, 2, 1, 0, 1, 0, 0, 2, 1, 0, 0])
s2 = np.array([0., 1, 2, 3, 1, 0, 0, 0, 2, 1, 0, 0, 0])
path = dtw.warping_path(s1, s2)
dtwvis.plot_warping(s1, s2, path, filename="warp.png")
เฉพาะการวัดระยะทางตามลำดับตัวเลขสองลำดับเท่านั้น:
from dtaidistance import dtw
s1 = [0, 0, 1, 2, 1, 0, 1, 0, 0]
s2 = [0, 1, 2, 0, 0, 0, 0, 0, 0]
distance = dtw.distance(s1, s2)
print(distance)
เวอร์ชันที่เร็วที่สุด (30-300 ครั้ง) ใช้ c โดยตรง แต่ต้องใช้อาร์เรย์เป็นอินพุต (ที่มีประเภทคู่) และ (เป็นทางเลือก) ยังตัดการคำนวณโดยการตั้งค่า max_dist
เป็นขอบเขตบนของยุคลิด:
from dtaidistance import dtw
import array
s1 = array.array('d',[0, 0, 1, 2, 1, 0, 1, 0, 0])
s2 = array.array('d',[0, 1, 2, 0, 0, 0, 0, 0, 0])
d = dtw.distance_fast(s1, s2, use_pruning=True)
หรือคุณสามารถใช้อาร์เรย์ numpy (ด้วย dtype double หรือ float):
from dtaidistance import dtw
import numpy as np
s1 = np.array([0, 0, 1, 2, 1, 0, 1, 0, 0], dtype=np.double)
s2 = np.array([0.0, 1, 2, 0, 0, 0, 0, 0, 0])
d = dtw.distance_fast(s1, s2, use_pruning=True)
ตรวจสอบ __doc__
สำหรับข้อมูลเกี่ยวกับข้อโต้แย้งที่มีอยู่:
print(dtw.distance.__doc__)
คาดว่าจะมีตัวเลือกจำนวนหนึ่งในการหยุดเส้นทางบางเส้นทางที่อัลกอริธึมการเขียนโปรแกรมแบบไดนามิกกำลังสำรวจหรือปรับแต่งการคำนวณการวัดระยะทาง:
window
: อนุญาตให้เลื่อนห่างจากเส้นทแยงมุมทั้งสองได้ถึงจำนวนนี้เท่านั้นmax_dist
: หยุดหากการวัดระยะทางที่ส่งคืนจะมากกว่าค่านี้max_step
: ไม่อนุญาตให้มีขั้นตอนที่ใหญ่กว่าค่านี้max_length_diff
: ส่งคืนค่าอนันต์หากความยาวของสองซีรี่ส์ต่างกันมากกว่าpenalty
: บทลงโทษที่จะเพิ่มหากใช้การบีบอัดหรือการขยาย (ด้านบนของระยะทาง)psi
: การคลายตัวของ Psi เพื่อละเว้นจุดเริ่มต้นและ/หรือจุดสิ้นสุดของลำดับ (สำหรับลำดับทรงกระบอก) [2]use_pruning
: การคำนวณแบบพรุนตามขอบเขตบนของยุคลิด ถัดจากระยะทาง หากคุณต้องการให้เมทริกซ์เต็มเห็นเส้นทางการบิดเบี้ยวที่เป็นไปได้ทั้งหมด:
from dtaidistance import dtw
s1 = [0, 0, 1, 2, 1, 0, 1, 0, 0]
s2 = [0, 1, 2, 0, 0, 0, 0, 0, 0]
distance, paths = dtw.warping_paths(s1, s2)
print(distance)
print(paths)
เมทริกซ์ที่มีเส้นทางการบิดเบี้ยวทั้งหมดสามารถมองเห็นได้ดังนี้:
from dtaidistance import dtw
from dtaidistance import dtw_visualisation as dtwvis
import random
import numpy as np
x = np.arange(0, 20, .5)
s1 = np.sin(x)
s2 = np.sin(x - 1)
random.seed(1)
for idx in range(len(s2)):
if random.random() < 0.05:
s2[idx] += (random.random() - 0.5) / 2
d, paths = dtw.warping_paths(s1, s2, window=25, psi=2)
best_path = dtw.best_path(paths)
dtwvis.plot_warpingpaths(s1, s2, paths, best_path)
สังเกตพารามิเตอร์ psi
ที่จะผ่อนคลายการจับคู่ที่จุดเริ่มต้นและจุดสิ้นสุด ในตัวอย่างนี้ ผลลัพธ์ที่ได้คือการจับคู่ที่สมบูรณ์แบบ แม้ว่าคลื่นไซน์จะเปลี่ยนไปเล็กน้อยก็ตาม
หากต้องการคำนวณการวัดระยะทาง DTW ระหว่างลำดับทั้งหมดในรายการลำดับ ให้ใช้วิธีการ dtw.distance_matrix
คุณสามารถตั้งค่าตัวแปรให้ใช้โค้ด c มากขึ้นหรือน้อยลง ( use_c
และ use_nogil
) และการดำเนินการแบบขนานหรือแบบอนุกรม ( parallel
)
เมธอด distance_matrix
ต้องการรายการ/อาร์เรย์:
from dtaidistance import dtw
import numpy as np
series = [
np.array([0, 0, 1, 2, 1, 0, 1, 0, 0], dtype=np.double),
np.array([0.0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0]),
np.array([0.0, 0, 1, 2, 1, 0, 0, 0])]
ds = dtw.distance_matrix_fast(series)
หรือเมทริกซ์ (ในกรณีที่ทุกซีรีย์มีความยาวเท่ากัน):
from dtaidistance import dtw
import numpy as np
series = np.matrix([
[0.0, 0, 1, 2, 1, 0, 1, 0, 0],
[0.0, 1, 2, 0, 0, 0, 0, 0, 0],
[0.0, 0, 1, 2, 1, 0, 0, 0, 0]])
ds = dtw.distance_matrix_fast(series)
คุณสามารถสั่งให้การคำนวณกรอกเมทริกซ์การวัดระยะทางเพียงบางส่วนเท่านั้น ตัวอย่างเช่น เพื่อกระจายการคำนวณไปยังหลายโหนด หรือเพื่อเปรียบเทียบเฉพาะซีรีส์ต้นทางกับซีรีส์เป้าหมายเท่านั้น
from dtaidistance import dtw
import numpy as np
series = np.matrix([
[0., 0, 1, 2, 1, 0, 1, 0, 0],
[0., 1, 2, 0, 0, 0, 0, 0, 0],
[1., 2, 0, 0, 0, 0, 0, 1, 1],
[0., 0, 1, 2, 1, 0, 1, 0, 0],
[0., 1, 2, 0, 0, 0, 0, 0, 0],
[1., 2, 0, 0, 0, 0, 0, 1, 1]])
ds = dtw.distance_matrix_fast(series, block=((1, 4), (3, 5)))
ผลลัพธ์ในกรณีนี้จะเป็น:
# 0 1 2 3 4 5
[[ inf inf inf inf inf inf] # 0
[ inf inf inf 1.4142 0.0000 inf] # 1
[ inf inf inf 2.2360 1.7320 inf] # 2
[ inf inf inf inf 1.4142 inf] # 3
[ inf inf inf inf inf inf] # 4
[ inf inf inf inf inf inf]] # 5
สามารถใช้เมทริกซ์ระยะทางสำหรับการจัดกลุ่มอนุกรมเวลาได้ คุณสามารถใช้วิธีการที่มีอยู่ เช่น scipy.cluster.hierarchy.linkage
หรือหนึ่งในสองวิธีการจัดกลุ่มที่รวมอยู่ (วิธีหลังคือ wrapper สำหรับวิธีการเชื่อมโยง SciPy)
from dtaidistance import clustering
# Custom Hierarchical clustering
model1 = clustering.Hierarchical(dtw.distance_matrix_fast, {})
cluster_idx = model1.fit(series)
# Augment Hierarchical object to keep track of the full tree
model2 = clustering.HierarchicalTree(model1)
cluster_idx = model2.fit(series)
# SciPy linkage clustering
model3 = clustering.LinkageTree(dtw.distance_matrix_fast, {})
cluster_idx = model3.fit(series)
สำหรับโมเดลที่ติดตามแผนผังการจัดกลุ่มแบบเต็ม ( HierarchicalTree
หรือ LinkageTree
) สามารถมองเห็นแผนผังได้:
model.plot("myplot.png")
ไม่จำเป็น:
การพัฒนา:
DTAI distance code.
Copyright 2016-2022 KU Leuven, DTAI Research Group
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.