ইউপ্লিডিয়ান দূরত্ব কীভাবে নুমপির সাহায্যে গণনা করা যায়?


529

আমার 3D এ দুটি পয়েন্ট রয়েছে:

(xa, ya, za)
(xb, yb, zb)

এবং আমি দূরত্ব গণনা করতে চাই:

dist = sqrt((xa-xb)^2 + (ya-yb)^2 + (za-zb)^2)

নুমপি বা সাধারণভাবে পাইথনের সাথে এটি করার সর্বোত্তম উপায় কী? আমার আছে:

import numpy
a = numpy.array((xa ,ya, za))
b = numpy.array((xb, yb, zb))

উত্তর:


883

ব্যবহার numpy.linalg.norm:

dist = numpy.linalg.norm(a-b)

আপনি এর পিছনে তত্ত্বটি ডেটা মাইনিংয়ের পরিচিতিতে খুঁজে পেতে পারেন

এই কাজ কারণ ইউক্লিডিয় দূরত্ব হয় L2 আদর্শ এবং ডিফল্ট মান Ord numpy.linalg.norm মাপদণ্ড 2।

এখানে চিত্র বর্ণনা লিখুন


13
লিনালগ.অর্নাম ডক্সটি এখানে পাওয়া যাবে: ডকস.সসিপি.আর / ডক / নম্পি / রেফারেন্স / জেনারেটেড / আমার একমাত্র আসল মন্তব্যটি একটি আদর্শের মধ্যে সংযোগটি নির্দেশ করার মতো ছিল (এই ক্ষেত্রে ফ্রোবেনিয়াস নর্ম / ২-আদর্শ যা আদর্শ ফাংশনের জন্য ডিফল্ট) এবং একটি মেট্রিক (এই ক্ষেত্রে ইউক্লিডিয়ান দূরত্ব)।
মার্ক লাভভিন 20

7
ওপি যদি স্থানাঙ্কগুলির একটি অ্যারের মধ্যে দূরত্ব গণনা করতে চায় তবে scipy.spatial.distance.cdist ব্যবহার করাও সম্ভব ।
mnky9800n

2
আমার প্রশ্ন: এর বিপরীতে কেন এটি ব্যবহার করবেন? stackoverflow.com/a/21986532/189411 scipy.spatial আমদানি দূর থেকে একটি = (1,2,3) খ = (4,5,6) DST = distance.euclidean (ক, খ)
Domenico মোনাকো

2
সায়পাইয়ের সিডিস্ট ফাংশনে আপডেট হওয়া লিঙ্ক: ডকস.সসিপি.আর
স্টিভেন সি হাওল

numpy.linalg.norm এর থেকেও আরও বেশি দ্রুত পদ্ধতি রয়েছে: semantive.com/blog/…
মুহাম্মদ আশফাক

161

সায়পাইতে এর জন্য একটি ফাংশন রয়েছে। একে ইউক্লিডিয়ান বলা হয় ।

উদাহরণ:

from scipy.spatial import distance
a = (1, 2, 3)
b = (4, 5, 6)
dst = distance.euclidean(a, b)

56
আপনি যদি দক্ষতার সন্ধান করেন তবে নিমপি ফাংশনটি ব্যবহার করা ভাল। স্কিপি দূরত্ব numpy.linalg.norm (আব) (এবং numpy.sqrt (numpy.sum ((আব)) ** 2%)) এর দ্বিগুণ ধীর। আমার মেশিনে আমি স্কিপি (v0.15.1) এর সাথে 19.7 and এবং নপি (v1.9.2) সহ 8.9। এস পাই। অনেক ক্ষেত্রে প্রাসঙ্গিক পার্থক্য নয় তবে লুপে থাকলে আরও তাৎপর্যপূর্ণ হয়ে উঠতে পারে। স্কিপি কোডটিতে তাত্ক্ষণিকভাবে দেখে মনে হচ্ছে এটি ধীর হয়ে গেছে কারণ এটি দূরত্ব গণনার আগে অ্যারেটিকে বৈধতা দেয়।
অ্যালগোল্ড

@ মাইকপ্যালাইমস হ্যাঁ, স্কিপি ফাংশনগুলি নম্পদের সাথে সম্পূর্ণ সুসংগত। কিন্তু এখানে কি প্রস্তাব aigold কটাক্ষপাত (এটিও অবশ্যই numpy অ্যারে কাজ করে,) নিতে
Avision

@ আমার ম্যাট্রিকগুলিতে বিভিন্ন সংখ্যক সারি রয়েছে বলে এটি আমার পক্ষে কাজ করবে কিনা তা নিশ্চিত নয়; একটি ম্যাট্রিক্স পাওয়ার জন্য তাদের বিয়োগের চেষ্টা করা কাজ করে না
বোজর্কস এক নম্বর ভক্ত

@ মাইকপ্যালাইমস আপনি এই দুটি ম্যাট্রিকের সাথে গণনা করার জন্য ঠিক কী চেষ্টা করছেন? প্রত্যাশিত ইনপুট / আউটপুট কি?
Avision

অনুসরণ করার জন্য ty। এখানে একটি বিবরণ রয়েছে: stats.stackexchange.com/questions/322620/… । আমার কাছে 'অপারেশন' এর 2 টি টেবিল রয়েছে; প্রত্যেকের একটি 'কোড' লেবেল রয়েছে তবে লেবেলের দুটি সেট সম্পূর্ণ আলাদা। আমার লক্ষ্যটি হ'ল প্রথম টেবিলের মধ্যে একটি নির্দিষ্ট কোডের সাথে সাদৃশ্যযুক্ত সেরা বা নিকটতম কোডটি সন্ধান করা (আমি জানি ম্যানুয়াল পরিদর্শন থেকে উত্তরটি কী হওয়া উচিত তবে পরে শত শত টেবিল পর্যন্ত স্কেল করতে চাই)। সুতরাং প্রথম উপসেটটি স্থির হয়েছে; আমি এই এবং 2 য় এর সমস্ত কোড সাবটেটের গড় হিসাব করি, তারপরে বাছাই করুন
16:30

108

একবারে একাধিক দূরত্ব গণনা করতে আগ্রহী যে কারও জন্য, আমি পারফ্লোট (আমার একটি ছোট প্রকল্প) ব্যবহার করে কিছুটা তুলনা করেছি ।

প্রথম পরামর্শটি হ'ল আপনার ডেটাটি এমনভাবে সাজানো যাতে অ্যারেগুলির মাত্রা থাকে (3, n)(এবং এটি স্পষ্টত সি-স্বচ্ছল)। যোগ সংলগ্ন প্রথম মাত্রা মধ্যে এমনটা হয়, তাহলে কিছু দ্রুত, এবং এটি না ব্যাপার অত্যধিক যদি আপনি ব্যবহার করে sqrt-sumসঙ্গে axis=0, linalg.normসঙ্গে axis=0, অথবা

a_min_b = a - b
numpy.sqrt(numpy.einsum('ij,ij->j', a_min_b, a_min_b))

যা সামান্য ব্যবধানে, দ্রুততম বৈকল্পিক। (এটি সত্য মাত্র এক সারির জন্যও সত্য holds

দ্বিতীয় অক্ষের উপরে আপনি যে রূপগুলি যোগ করেন axis=1, সবগুলি যথেষ্ট ধীর।

এখানে চিত্র বর্ণনা লিখুন


প্লটটি পুনরুত্পাদন করার কোড:

import numpy
import perfplot
from scipy.spatial import distance


def linalg_norm(data):
    a, b = data[0]
    return numpy.linalg.norm(a - b, axis=1)


def linalg_norm_T(data):
    a, b = data[1]
    return numpy.linalg.norm(a - b, axis=0)


def sqrt_sum(data):
    a, b = data[0]
    return numpy.sqrt(numpy.sum((a - b) ** 2, axis=1))


def sqrt_sum_T(data):
    a, b = data[1]
    return numpy.sqrt(numpy.sum((a - b) ** 2, axis=0))


def scipy_distance(data):
    a, b = data[0]
    return list(map(distance.euclidean, a, b))


def sqrt_einsum(data):
    a, b = data[0]
    a_min_b = a - b
    return numpy.sqrt(numpy.einsum("ij,ij->i", a_min_b, a_min_b))


def sqrt_einsum_T(data):
    a, b = data[1]
    a_min_b = a - b
    return numpy.sqrt(numpy.einsum("ij,ij->j", a_min_b, a_min_b))


def setup(n):
    a = numpy.random.rand(n, 3)
    b = numpy.random.rand(n, 3)
    out0 = numpy.array([a, b])
    out1 = numpy.array([a.T, b.T])
    return out0, out1


perfplot.save(
    "norm.png",
    setup=setup,
    n_range=[2 ** k for k in range(22)],
    kernels=[
        linalg_norm,
        linalg_norm_T,
        scipy_distance,
        sqrt_sum,
        sqrt_sum_T,
        sqrt_einsum,
        sqrt_einsum_T,
    ],
    logx=True,
    logy=True,
    xlabel="len(x), len(y)",
)

3
ধন্যবাদ. আমি আজ নতুন কিছু শিখেছি! একক মাত্রার অ্যারের জন্য, স্ট্রিংটি হবেi,i->
তীর্থ

4
স্মৃতি
শক্তিগুলির

আমি আপনার কোডটি ব্যবহার করতে চাই তবে ডেটা কীভাবে সাজানো হবে তা বোঝার জন্য আমি লড়াই করে যাচ্ছি। আপনি কি একটি উদাহরণ দিতে পারেন? দেখতে কেমন লাগে data?
জোহানেস উইসনার

1
সত্যিই ঝরঝরে প্রকল্প এবং অনুসন্ধানগুলি। আমি একই প্রকৃতির কিছু অর্ধেক *** এড প্লট করছি, তাই আমি মনে করি আপনার প্রকল্পে স্যুইচ করব এবং পার্থক্যগুলি অবদান রাখব, যদি আপনি এটি পছন্দ করেন।
ম্যাড পদার্থবিদ

42

আমি বিভিন্ন পারফরম্যান্স নোট সহ সহজ উত্তরটি ব্যাখ্যা করতে চাই। np.linalg.norm আপনার প্রয়োজনের চেয়ে আরও বেশি কিছু করবে:

dist = numpy.linalg.norm(a-b)

প্রথমত - এই ফাংশনটি একটি তালিকার উপরে কাজ করে এবং সমস্ত মানগুলি ফেরত দেওয়ার জন্য ডিজাইন করা হয়েছে, উদাহরণস্বরূপ pAপয়েন্টগুলির সেট থেকে দূরত্বের তুলনা করতে sP:

sP = set(points)
pA = point
distances = np.linalg.norm(sP - pA, ord=2, axis=1.)  # 'distances' is a list

কয়েকটি জিনিস মনে রাখবেন:

  • পাইথন ফাংশন কলগুলি ব্যয়বহুল।
  • [নিয়মিত] পাইথন নামের সন্ধানগুলি ক্যাশে করে না।

সুতরাং

def distance(pointA, pointB):
    dist = np.linalg.norm(pointA - pointB)
    return dist

দেখতে যতটা নির্দোষ তা নয়

>>> dis.dis(distance)
  2           0 LOAD_GLOBAL              0 (np)
              2 LOAD_ATTR                1 (linalg)
              4 LOAD_ATTR                2 (norm)
              6 LOAD_FAST                0 (pointA)
              8 LOAD_FAST                1 (pointB)
             10 BINARY_SUBTRACT
             12 CALL_FUNCTION            1
             14 STORE_FAST               2 (dist)

  3          16 LOAD_FAST                2 (dist)
             18 RETURN_VALUE

প্রথমত - যতবার আমরা এটি ডাকি, আমাদের "এনপি" এর জন্য একটি বিশ্বব্যাপী অনুসন্ধান করতে হবে, "লিনালগ" এর জন্য একটি স্কোপযুক্ত অনুসন্ধান এবং "আদর্শ" এর জন্য একটি স্কোপযুক্ত অনুসন্ধান করতে হবে এবং কেবলমাত্র ফাংশনটি কল করার ওভারহেড কয়েক ডজন পাইথনের সমান হতে পারে নির্দেশাবলী।

সবশেষে, আমরা ফলাফল সংরক্ষণ করতে এবং দুটি পুনরায় লোড করার জন্য দুটি অপারেশন নষ্ট করেছি ...

উন্নতিতে প্রথম পাস: দ্রুত অনুসন্ধান করুন, স্টোরটি এড়িয়ে যান

def distance(pointA, pointB, _norm=np.linalg.norm):
    return _norm(pointA - pointB)

আমরা আরও বেশি প্রবাহিত পাই:

>>> dis.dis(distance)
  2           0 LOAD_FAST                2 (_norm)
              2 LOAD_FAST                0 (pointA)
              4 LOAD_FAST                1 (pointB)
              6 BINARY_SUBTRACT
              8 CALL_FUNCTION            1
             10 RETURN_VALUE

যদিও ফাংশন কল ওভারহেড এখনও কিছু কাজের পরিমাণ। আপনি নিজেই গণিতটি আরও ভাল করছেন কিনা তা নির্ধারণ করতে আপনি মানদণ্ডগুলি করতে চাইবেন:

def distance(pointA, pointB):
    return (
        ((pointA.x - pointB.x) ** 2) +
        ((pointA.y - pointB.y) ** 2) +
        ((pointA.z - pointB.z) ** 2)
    ) ** 0.5  # fast sqrt

কিছু প্ল্যাটফর্মে, এর **0.5চেয়ে দ্রুত math.sqrt। আপনার মাইলেজ পরিবর্তিত হতে পারে.

**** উন্নত পারফরম্যান্স নোট।

কেন আপনি দূরত্ব গণনা করছেন? যদি একমাত্র উদ্দেশ্য এটি প্রদর্শিত হয়,

 print("The target is %.2fm away" % (distance(a, b)))

বরাবর অগ্রসর. তবে আপনি যদি দূরত্বের তুলনা করে, পরিসীমা চেক ইত্যাদি করেন, আমি কিছু কার্যকর সম্পাদনা পর্যবেক্ষণ যোগ করতে চাই।

আসুন দুটি ক্ষেত্রে নেওয়া যাক: দূরত্ব অনুসারে বাছাই করা বা আইটেমগুলিতে একটি সীমাবদ্ধতা বা সীমার সীমাবদ্ধতা পূরণ করে to

# Ultra naive implementations. Hold onto your hat.

def sort_things_by_distance(origin, things):
    return things.sort(key=lambda thing: distance(origin, thing))

def in_range(origin, range, things):
    things_in_range = []
    for thing in things:
        if distance(origin, thing) <= range:
            things_in_range.append(thing)

আমাদের প্রথমটি মনে রাখতে হবে যে আমরা পাইথাগোরাস ব্যবহার dist = sqrt(x^2 + y^2 + z^2)করছি দূরত্ব গণনা করতে ( ) তাই আমরা প্রচুর sqrtকল করছি। গণিত 101:

dist = root ( x^2 + y^2 + z^2 )
:.
dist^2 = x^2 + y^2 + z^2
and
sq(N) < sq(M) iff M > N
and
sq(N) > sq(M) iff N > M
and
sq(N) = sq(M) iff N == M

সংক্ষেপে: যতক্ষণ না আমরা X ^ 2 এর পরিবর্তে X এর এককে দূরত্বের প্রয়োজন হয়, ততক্ষণ আমরা গণনার সবচেয়ে শক্ত অংশটি নির্মূল করতে পারি।

# Still naive, but much faster.

def distance_sq(left, right):
    """ Returns the square of the distance between left and right. """
    return (
        ((left.x - right.x) ** 2) +
        ((left.y - right.y) ** 2) +
        ((left.z - right.z) ** 2)
    )

def sort_things_by_distance(origin, things):
    return things.sort(key=lambda thing: distance_sq(origin, thing))

def in_range(origin, range, things):
    things_in_range = []

    # Remember that sqrt(N)**2 == N, so if we square
    # range, we don't need to root the distances.
    range_sq = range**2

    for thing in things:
        if distance_sq(origin, thing) <= range_sq:
            things_in_range.append(thing)

দুর্দান্ত, উভয় ফাংশন আর কোনও ব্যয়বহুল স্কোয়ার শিকড় করবে না। এটি আরও দ্রুত হবে। আমরা জেনারেটরে রূপান্তর করে ইন-অ্যারেঞ্জও উন্নত করতে পারি:

def in_range(origin, range, things):
    range_sq = range**2
    yield from (thing for thing in things
                if distance_sq(origin, thing) <= range_sq)

আপনি যদি এমন কিছু করেন তবে এটির সুবিধাগুলি রয়েছে:

if any(in_range(origin, max_dist, things)):
    ...

তবে আপনি যদি করতে যাচ্ছেন তার পরেরটির জন্য যদি একটি দূরত্ব প্রয়োজন,

for nearby in in_range(origin, walking_distance, hotdog_stands):
    print("%s %.2fm" % (nearby.name, distance(origin, nearby)))

ফলনশীল tuples বিবেচনা করুন:

def in_range_with_dist_sq(origin, range, things):
    range_sq = range**2
    for thing in things:
        dist_sq = distance_sq(origin, thing)
        if dist_sq <= range_sq: yield (thing, dist_sq)

এটি বিশেষত কার্যকর হতে পারে যদি আপনি পরিসীমা চেকগুলি চেন করতে পারেন ('এক্স এর কাছাকাছি এবং Y এর Nm এর মধ্যে এমন জিনিসগুলি সন্ধান করুন', কারণ আপনাকে আবার দূরত্ব গণনা করতে হবে না)।

তবে যদি আমরা সত্যিই একটি বৃহত তালিকা অনুসন্ধান thingsকরি এবং আমরা তাদের মধ্যে অনেকের বিবেচনার যোগ্য নয় বলে প্রত্যাশা করি তবে কী হবে?

আসলে খুব সাধারণ অপ্টিমাইজেশন রয়েছে:

def in_range_all_the_things(origin, range, things):
    range_sq = range**2
    for thing in things:
        dist_sq = (origin.x - thing.x) ** 2
        if dist_sq <= range_sq:
            dist_sq += (origin.y - thing.y) ** 2
            if dist_sq <= range_sq:
                dist_sq += (origin.z - thing.z) ** 2
                if dist_sq <= range_sq:
                    yield thing

এটি কার্যকর কিনা তা 'জিনিসগুলির' আকারের উপর নির্ভর করবে।

def in_range_all_the_things(origin, range, things):
    range_sq = range**2
    if len(things) >= 4096:
        for thing in things:
            dist_sq = (origin.x - thing.x) ** 2
            if dist_sq <= range_sq:
                dist_sq += (origin.y - thing.y) ** 2
                if dist_sq <= range_sq:
                    dist_sq += (origin.z - thing.z) ** 2
                    if dist_sq <= range_sq:
                        yield thing
    elif len(things) > 32:
        for things in things:
            dist_sq = (origin.x - thing.x) ** 2
            if dist_sq <= range_sq:
                dist_sq += (origin.y - thing.y) ** 2 + (origin.z - thing.z) ** 2
                if dist_sq <= range_sq:
                    yield thing
    else:
        ... just calculate distance and range-check it ...

এবং আবারও, ডিস্ট_স্কুয়ার ফলন বিবেচনা করুন। আমাদের হটডগ উদাহরণটি তখন পরিণত হয়:

# Chaining generators
info = in_range_with_dist_sq(origin, walking_distance, hotdog_stands)
info = (stand, dist_sq**0.5 for stand, dist_sq in info)
for stand, dist in info:
    print("%s %.2fm" % (stand, dist))

1
কেন এইরকম অপটিমাইজড ক্রিয়াকলাপটি নিম্পে যুক্ত করবেন না? পান্ডাসের জন্য একটি এক্সটেনশানও এই স্ট্যাকওভারফ্লো.com
কিথ

3
আমি আপনার প্রথম গাণিতিক পদ্ধতির দূরত্ব সম্পাদনা করেছি। আপনি এমন একটি ব্যবহার pointZকরছিলেন যা বিদ্যমান ছিল না। আমি মনে করি আপনি যা বোঝাতে চেয়েছিলেন তা ত্রি-মাত্রিক স্থানে দুটি পয়েন্ট ছিল এবং আমি সেই অনুযায়ী সম্পাদনা করেছি। যদি আমি ভুল ছিলাম, দয়া করে আমাকে জানান।
ব্রাম ভ্যানরোয়

37

এই সমস্যা সমাধানের পদ্ধতির আরেকটি উদাহরণ :

def dist(x,y):   
    return numpy.sqrt(numpy.sum((x-y)**2))

a = numpy.array((xa,ya,za))
b = numpy.array((xb,yb,zb))
dist_a_b = dist(a,b)

1
আপনি কি নম্পির স্কয়ার্ট এবং / অথবা যোগফলগুলি ব্যবহার করতে পারেন? এটি দ্রুত করা উচিত (?)
u0b34a0f6ae

1
আমি এটি ইন্টারভ্যুজের অন্যদিকে পেয়েছি norm = lambda x: N.sqrt(N.square(x).sum()); norm(x-y)
u0b34a0f6ae

2
যে আঁচড়ের দাগ. এটা কোথাও হতে হবে। এখানে এটি:numpy.linalg.norm(x-y)
u0b34a0f6ae

13

শুরু করে Python 3.8, mathমডিউলটি সরাসরি distফাংশন সরবরাহ করে , যা দুটি পয়েন্টের মধ্যে ইউক্লিডিয়ান দূরত্ব দেয় (টিউপলস বা স্থানাঙ্কের তালিকা হিসাবে দেওয়া হয়):

from math import dist

dist((1, 2, 6), (-2, 3, 2)) # 5.0990195135927845

এবং যদি আপনি তালিকাগুলি নিয়ে কাজ করছেন:

dist([1, 2, 6], [-2, 3, 2]) # 5.0990195135927845

12

এটি নিম্নলিখিত মত করা যেতে পারে। আমি জানি না এটি কত দ্রুত, তবে এটি নম্পপি ব্যবহার করছে না।

from math import sqrt
a = (1, 2, 3) # Data point 1
b = (4, 5, 6) # Data point 2
print sqrt(sum( (a - b)**2 for a, b in zip(a, b)))

অজগরটিতে সরাসরি গণিত করা ভাল ধারণা নয় কারণ বিশেষত অজগর খুব ধীর for a, b in zip(a, b)। কিন্তু দরকারী কম।
সিগেক্স

10

আমি matplotlib.mlab এ একটি 'ডিস্ট' ফাংশন পাই, তবে আমি মনে করি না এটি যথেষ্ট কার্যকর think

আমি এখানে এখানে রেফারেন্স পোস্ট করছি।

import numpy as np
import matplotlib as plt

a = np.array([1, 2, 3])
b = np.array([2, 3, 4])

# Distance between a and b
dis = plt.mlab.dist(a, b)

এটি আর প্রযোজ্য নয়। (এমপিএল 3.0)
নিকো শ্ল্যামার

8

আমি পছন্দ করি np.dot(বিন্দু পণ্য):

a = numpy.array((xa,ya,za))
b = numpy.array((xb,yb,zb))

distance = (np.dot(a-b,a-b))**.5

8

একটি দুর্দান্ত এক-লাইনার:

dist = numpy.linalg.norm(a-b)

তবে, গতি যদি উদ্বেগজনক হয় তবে আমি আপনার মেশিনে পরীক্ষার পরামর্শ দেব। আমি দেখতে পেয়েছি যে বর্গক্ষেত্রের জন্য অপারেটরের সাথে mathলাইব্রেরি ব্যবহার করা আমার মেশিনে ওয়ান-লাইনার নম্পপি সমাধানের চেয়ে আরও দ্রুত।sqrt**

আমি এই সাধারণ প্রোগ্রামটি ব্যবহার করে আমার পরীক্ষা চালিয়েছি:

#!/usr/bin/python
import math
import numpy
from random import uniform

def fastest_calc_dist(p1,p2):
    return math.sqrt((p2[0] - p1[0]) ** 2 +
                     (p2[1] - p1[1]) ** 2 +
                     (p2[2] - p1[2]) ** 2)

def math_calc_dist(p1,p2):
    return math.sqrt(math.pow((p2[0] - p1[0]), 2) +
                     math.pow((p2[1] - p1[1]), 2) +
                     math.pow((p2[2] - p1[2]), 2))

def numpy_calc_dist(p1,p2):
    return numpy.linalg.norm(numpy.array(p1)-numpy.array(p2))

TOTAL_LOCATIONS = 1000

p1 = dict()
p2 = dict()
for i in range(0, TOTAL_LOCATIONS):
    p1[i] = (uniform(0,1000),uniform(0,1000),uniform(0,1000))
    p2[i] = (uniform(0,1000),uniform(0,1000),uniform(0,1000))

total_dist = 0
for i in range(0, TOTAL_LOCATIONS):
    for j in range(0, TOTAL_LOCATIONS):
        dist = fastest_calc_dist(p1[i], p2[j]) #change this line for testing
        total_dist += dist

print total_dist

আমার মেশিনে, ২৩.৫ সেকেন্ডের math_calc_distতুলনায় numpy_calc_dist1.5 সেকেন্ডের চেয়ে অনেক বেশি দ্রুত চলে ।

মধ্যে একটি পরিমাপযোগ্য পার্থক্য পেতে fastest_calc_distএবং math_calc_distআমি ছিল TOTAL_LOCATIONS6000. তারপর fastest_calc_dist50 সেকেন্ড সময় লাগে ~ যখন math_calc_dist60 সেকেন্ড সময় লাগে ~।

আপনি পরীক্ষা করতে পারেন numpy.sqrtএবং numpy.squareযদিও উভয়ই mathআমার মেশিনের বিকল্পগুলির চেয়ে ধীর ছিল ।

আমার পরীক্ষাগুলি পাইথন ২.6..6 দিয়ে চালানো হয়েছিল।


48
আপনি কীভাবে ন্যাম্পি ব্যবহার করবেন তা খারাপভাবে বোঝা যাচ্ছেন ... লুপ বা তালিকা বোঝার জন্য ব্যবহার করবেন না । যদি আপনি পুনরাবৃত্তি করে থাকেন এবং প্রতিটি আইটেমটিতে ফাংশনটি প্রয়োগ করেন তবে হ্যাঁ, অসাধারণ ফাংশনগুলি ধীর হবে be পুরো বিষয়টি হ'ল জিনিসগুলি ভেক্টরাইজ করা।
জো কিংটন

আমি যদি নমপি.আররে কলটি লুপটিতে স্থানান্তরিত করি যেখানে আমি পয়েন্টগুলি তৈরি করছি আমি নাম্পি_ক্যাল্যাক_ডিজ্টের সাথে আরও ভাল ফলাফল পেয়েছি তবে এটি দ্রুততম_ক্যাল্ক_ডিস্টের চেয়ে 10x ধীর গতির। আমার যদি এমন অনেকগুলি পয়েন্ট থাকে এবং প্রতিটি জোড়ার মধ্যবর্তী দূরত্বটি আমার সন্ধান করতে হয় তবে আমি জানি না যে আমি নম্পতির সুবিধার্থে আরও কী করতে পারি।
ব্যবহারকারী 118662

15
আমি বুঝতে পারি যে এই থ্রেডটি পুরানো, তবে জো যা বলেছিল তা আমি কেবল আরও শক্তিশালী করতে চাই। আপনি নাম্পাতটি সঠিকভাবে ব্যবহার করছেন না। আপনি যা গণনা করছেন তা হ'ল পি 1 এর প্রতিটি বিন্দু থেকে পি 2 এর প্রতিটি পয়েন্টের দূরত্বের যোগফল। ন্যাপি / স্কিপিযুক্ত সমাধানটি আমার মেশিনে 70 গুণ বেশি দ্রুত। P1 এবং p2 কে একটি অ্যারেতে তৈরি করুন (এমনকি লুপ ব্যবহার করে যদি সেগুলি ডিক্ট হিসাবে সংজ্ঞায়িত করা হয়)। তারপরে আপনি এক ধাপে মোট যোগফল পেতে পারেন scipy.spatial.distance.cdist(p1, p2).sum(),। হ্যাঁ, ওটাই.
স্কট বি

3
অথবা numpy.linalg.norm(p1-p2).sum()পি 1 এর প্রতিটি পয়েন্ট এবং পি 2 এর সাথে সম্পর্কিত পয়েন্টের মধ্যে যোগফল পেতে ব্যবহার করুন (অর্থাত্ প 1 এর প্রতিটি বিন্দুতে পি 2 এর প্রতিটি পয়েন্ট নয়)। এবং আপনি যদি পি 1 এর প্রতিটি বিন্দু পি 2 এর প্রতিটি বিন্দুতে চান এবং আমার আগের মতামত মতো স্কিপি ব্যবহার করতে না চান তবে আপনি এখনও এটি করতে আরও অনেক দ্রুত করতে nump.linalg.norm এর সাথে np.apply_along_axis ব্যবহার করতে পারেন তারপরে আপনার "দ্রুততম" সমাধান।
স্কট বি

2
NumPy এর পূর্ববর্তী সংস্করণগুলিতে খুব ধীর মান প্রয়োগ ছিল। বর্তমান সংস্করণগুলিতে, এই সমস্তগুলির প্রয়োজন নেই।
ফ্রেড ফু

8

আপনি কেবল ভেক্টরগুলি বিয়োগ করতে পারেন এবং তারপরে অভ্যন্তরীণ উত্পাদন করতে পারেন।

আপনার উদাহরণ অনুসরণ করে,

a = numpy.array((xa, ya, za))
b = numpy.array((xb, yb, zb))

tmp = a - b
sum_squared = numpy.dot(tmp.T, tmp)
result = sqrt(sum_squared)

5
এটি আমাকে দূরত্বের স্কোয়ার দেবে। আপনি এখানে একটি স্কয়ার্ট মিস করছেন।
নাথান ফেলম্যান


6

পাইথন ৩.৮ সহ এটি খুব সহজ।

https://docs.python.org/3/library/math.html#math.dist

math.dist(p, q)

দুটি বিন্দু পি এবং কিউর মধ্যে ইউক্লিডিয়ান দূরত্ব ফিরিয়ে আনুন, প্রত্যেকটি স্থানাঙ্কের সিক্যুয়েন্স (বা পুনরাবৃত্ত) হিসাবে দেওয়া হয়। দুটি পয়েন্টের অবশ্যই একই মাত্রা থাকতে হবে।

মোটামুটি সমান:

sqrt(sum((px - qx) ** 2.0 for px, qx in zip(p, q)))


5

পাইথনে ইউক্লিডিয়ান দূরত্বের জন্য কয়েকটি সংক্ষিপ্ত কোড এখানে পাইথনের দুটি তালিকা হিসাবে প্রতিনিধিত্ব করা হয়েছে।

def distance(v1,v2): 
    return sum([(x-y)**2 for (x,y) in zip(v1,v2)])**(0.5)

1
নম্পি ইনপুট হিসাবে তালিকাও গ্রহণ করে (স্পষ্ট করে একটি অদ্ভুত অ্যারে পাস করার প্রয়োজন নেই)
আলেজান্দ্রো সাজো

4

পাইথন ৩.৮

পাইথন ৩.৮ যেহেতু mathমডিউলটিতে ফাংশন অন্তর্ভুক্ত রয়েছে math.dist()
এখানে https://docs.python.org/3.8/library/math.html#math.dist দেখুন ।

math.dist (p1, p2)
দুটি পয়েন্ট পি 1 এবং পি 2 এর মধ্যে ইউক্লিডিয়ান দূরত্বটি প্রদান করুন, প্রত্যেকটি স্থানাঙ্কের ক্রম (বা পুনরাবৃত্ত) হিসাবে দেওয়া হবে।

import math
print( math.dist( (0,0),   (1,1)   )) # sqrt(2) -> 1.4142
print( math.dist( (0,0,0), (1,1,1) )) # sqrt(3) -> 1.7321

3

বহুমাত্রিক জায়গার জন্য ইউক্লিডিয়ান দূরত্ব গণনা করুন:

 import math

 x = [1, 2, 6] 
 y = [-2, 3, 2]

 dist = math.sqrt(sum([(xi-yi)**2 for xi,yi in zip(x, y)]))
 5.0990195135927845



2

আপনি সহজেই সূত্রটি ব্যবহার করতে পারেন

distance = np.sqrt(np.sum(np.square(a-b)))

actuallyx, andy এবং Δz এর বর্গাকার যোগ করে ফলাফলকে মূলোৎপাটন করে দূরত্ব নির্ণয়ের জন্য পাইথাগোরসের উপপাদ্যটি ব্যবহার করা ছাড়া আর কিছুই নেই।


1

প্রথমে দুটি ম্যাট্রিকের পার্থক্য সন্ধান করুন। তারপরে, নিমপির মাল্টিপল কমান্ড সহ উপাদান অনুসারে গুণিত প্রয়োগ করুন। এর পরে, মৌলিক গুণিত নতুন ম্যাট্রিক্সের সংমিশ্রণটি সন্ধান করুন। অবশেষে, যোগফলের বর্গমূল সন্ধান করুন।

def findEuclideanDistance(a, b):
    euclidean_distance = a - b
    euclidean_distance = np.sum(np.multiply(euclidean_distance, euclidean_distance))
    euclidean_distance = np.sqrt(euclidean_distance)
    return euclidean_distance

1
import numpy as np
# any two python array as two points
a = [0, 0]
b = [3, 4]

আপনি প্রথম পরিবর্তন তালিকা numpy অ্যারে এবং এই পছন্দ করি: print(np.linalg.norm(np.array(a) - np.array(b)))। পাইথন তালিকা থেকে সরাসরি দ্বিতীয় পদ্ধতি:print(np.linalg.norm(np.subtract(a,b)))

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.