مكتبة مسافات السلاسل الزمنية (مثل التشويه الزمني الديناميكي) المستخدمة في مجموعة أبحاث 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
الجديد في الإصدار الثاني :
ssize_t
بدلاً من int
يسمح بهياكل بيانات أكبر على أجهزة 64 بت ويكون أكثر توافقًا مع Numpy.max_dist
مشابهة لعمل سيلفا وباتيستا على PrunedDTW [7]. ينفذ صندوق الأدوات الآن إصدارًا مساوٍ لـ PrunedDTW نظرًا لأنه يقوم بتقليم المزيد من المسافات الجزئية. بالإضافة إلى ذلك، تمت إضافة وسيطة use_pruning
لتعيين max_dist
تلقائيًا على المسافة الإقليدية، كما اقترح سيلفا وباتيستا، لتسريع الحساب (تتوفر طريقة جديدة ub_euclidean
).dtaidistance.dtw_ndim
. $ pip install dtaidistance
أو
$ conda install -c conda-forge dtaidistance
يتطلب تثبيت النقطة 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
أو إحدى طريقتي التجميع المضمنتين (الأخيرة عبارة عن غلاف لأسلوب ربط 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.