নম্পপির আইসাম বোঝা


190

আমি ঠিক কীভাবে einsumকাজ করে তা বুঝতে সংগ্রাম করছি । আমি ডকুমেন্টেশন এবং কয়েকটি উদাহরণ দেখেছি, তবে এটি আটকে থাকা বলে মনে হচ্ছে না।

এখানে ক্লাসে আমরা গিয়েছিলাম এমন একটি উদাহরণ:

C = np.einsum("ij,jk->ki", A, B)

দুটি অ্যারে AএবংB

আমি মনে করি এটি নিবে A^T * B, তবে আমি নিশ্চিত নই (এটি ঠিক তাদের একজনের ট্রান্সপোজ নেওয়া হচ্ছে?)। এখানে কি ঘটছে (এবং সাধারণভাবে ব্যবহার করার সময় einsum) কেউ আমাকে ঠিক কীভাবে চলতে পারে ?


7
আসলে এটি হবে (A * B)^T, বা সমতুল্য B^T * A^T
টিগ্রান সালুয়েভ

20
আমি einsum এখানে এর বেসিক সম্পর্কে একটি ছোট ব্লগ পোস্ট লিখেছিলাম । (দরকারী হলে স্ট্যাক ওভারফ্লোতে একটি উত্তরের সর্বাধিক প্রাসঙ্গিক বিট প্রতিস্থাপনে আমি খুশি)
অ্যালেক্স রিলে

1
@ এজেসিআর - সুন্দর লিঙ্ক। ধন্যবাদ। numpyডকুমেন্টেশন শোচনীয়ভাবে অপর্যাপ্ত যখন বিবরণ ব্যাখ্যা নেই।
রেয়রিং

আত্মবিশ্বাসের ভোটের জন্য আপনাকে ধন্যবাদ! বিরক্তিকরভাবে, আমি নীচে একটি উত্তর অবদান রেখেছি ।
অ্যালেক্স রিলি

দ্রষ্টব্য যে পাইথন-এ *ম্যাট্রিক্সের গুণ নয়, মৌলিক দিকের গুণফল। সতর্ক থেকো!
কম্পিউটার

উত্তর:


368

(দ্রষ্টব্য: এই উত্তরটি আমি কিছুক্ষণ আগে লিখেছিলাম সে সম্পর্কে একটি ছোট ব্লগ পোস্টের উপর ভিত্তি করে einsum))

কি করে einsum?

কল্পনা করুন যে আমাদের দুটি বহুমাত্রিক অ্যারে রয়েছে Aএবং B। এখন ধরা যাক আমরা চাই ...

  • সংখ্যাবৃদ্ধি A সঙ্গে Bএকটি নির্দিষ্ট উপায় পণ্য নতুন অ্যারে তৈরি করার জন্য; এবং তারপর হতে পারে
  • নির্দিষ্ট অক্ষ বরাবর এই নতুন অ্যারের যোগফল ; এবং তারপর হতে পারে
  • একটি নির্দিষ্ট ক্রমে নতুন অ্যারের অক্ষগুলি স্থানান্তর করুন।

একটি ভাল সুযোগ আছে যে einsumআমাদের কি এই দ্রুত এবং আরো মেমরি দক্ষতার NumPy ফাংশন সমন্বয় চাই যে সাহায্য করবে multiply, sumএবং transposeঅনুমতি দেবে।

কিভাবে einsumকাজ করে?

এখানে একটি সাধারণ (তবে সম্পূর্ণ তুচ্ছ নয়) উদাহরণ's নিম্নলিখিত দুটি অ্যারে নিন:

A = np.array([0, 1, 2])

B = np.array([[ 0,  1,  2,  3],
              [ 4,  5,  6,  7],
              [ 8,  9, 10, 11]])

আমরা গুণবান Aএবং Bউপাদান-ভিত্তিক এবং তারপরে নতুন অ্যারের সারি বরাবর যোগ করব। "স্বাভাবিক" NumPy এ আমরা লিখতাম:

>>> (A[:, np.newaxis] * B).sum(axis=1)
array([ 0, 22, 76])

সুতরাং এখানে, Aদুটি অ্যারের প্রথম অক্ষটি রেখাগুলিতে সূচীকরণ অপারেশন যাতে গুণটি সম্প্রচার করা যায়। এরপরে পণ্যগুলির অ্যারেগুলির সারিগুলি উত্তর ফেরত দেওয়ার জন্য সংক্ষিপ্ত করে।

এখন যদি আমরা einsumপরিবর্তে ব্যবহার করতে চাই , আমরা লিখতে পারি:

>>> np.einsum('i,ij->i', A, B)
array([ 0, 22, 76])

স্বাক্ষর পংক্তি 'i,ij->i'কী এখানে এবং ব্যাখ্যা একটি সামান্য বিট প্রয়োজন। আপনি দুটি ভাগে এটি ভাবতে পারেন। বাম দিকে (বাম দিকে ->) আমরা দুটি ইনপুট অ্যারে লেবেল করেছি। এর ডানদিকে ->আমরা যে অ্যারেটি শেষ করতে চাই তা লেবেলযুক্ত করেছি।

এখানে যা ঘটেছিল তা এখানে:

  • Aএকটি অক্ষ আছে; আমরা এটি লেবেল করেছি i। এবং Bদুটি অক্ষ আছে; আমরা অক্ষ 0 হিসাবে iএবং অক্ষ 1 হিসাবে লেবেল করেছি j

  • দ্বারা পুনরায় ট্যাগ iউভয় ইনপুট অ্যারে, আমরা বলছেন einsumযে এই দুই অক্ষ হবে গুন একসঙ্গে। অন্য কথায়, আমরা অ্যারের Aপ্রতিটি কলামের সাথে অ্যারের গুণ করি B, ঠিক তেমন A[:, np.newaxis] * Bকরে।

  • লক্ষ্য করুন যে jআমাদের পছন্দসই আউটপুটে লেবেল হিসাবে উপস্থিত হবে না; আমরা সবেমাত্র ব্যবহার করেছি i(আমরা 1 ডি অ্যারে দিয়ে শেষ করতে চাই)। দ্বারা বাদ লেবেল, আমরা বলছ einsumকরার যোগফল এই অক্ষ বরাবর। অন্য কথায়, আমরা যেমন পণ্যগুলির সারিগুলি সংযুক্ত করছি .sum(axis=1)

এটি ব্যবহার করার জন্য আপনার যা জানা দরকার তা মূলত এটি einsum। এটি কিছুটা খেলতে সহায়তা করে; যদি আমরা আউটপুটে উভয় লেবেল রেখে থাকি 'i,ij->ij', আমরা পণ্যগুলির 2D অ্যারে (একই হিসাবে A[:, np.newaxis] * B) ফিরে পাই । যদি আমরা কোনও আউটপুট লেবেল না বলি তবে আমরা 'i,ij->একটি সংখ্যক সংকেত (করণের মতো (A[:, np.newaxis] * B).sum()) ফিরে পাই ।

তবে দুর্দান্ত জিনিসটি einsumহ'ল এটি হ'ল প্রথমে পণ্যগুলির অস্থায়ী বিন্যাস তৈরি করে না; এটি যেমন পণ্য যায় ঠিক তত পরিমাণে। এটি মেমরির ব্যবহারে বড় সঞ্চয় করতে পারে।

কিছুটা বড় উদাহরণ

ডট পণ্যটি ব্যাখ্যা করতে, এখানে দুটি নতুন অ্যারে রয়েছে:

A = array([[1, 1, 1],
           [2, 2, 2],
           [5, 5, 5]])

B = array([[0, 1, 0],
           [1, 1, 0],
           [1, 1, 1]])

আমরা ডট পণ্য ব্যবহার করে গণনা করব np.einsum('ij,jk->ik', A, B)। এখান থেকে লেবেল দেখানোর সময় একটি ছবি Aএবং Bএবং আউটপুট অ্যারে যে আমরা ফাংশন থেকে পাবেন:

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

আপনি দেখতে পাচ্ছেন যে লেবেলটি jপুনরাবৃত্তি হয়েছে - এর অর্থ আমরা Aএর কলামগুলির সাথে সারিগুলি গুণ করছি B। তদ্ব্যতীত, লেবেল jআউটপুট অন্তর্ভুক্ত করা হয় না - আমরা এই পণ্য সংক্ষেপে করছি। লেবেলগুলি iএবং kআউটপুট জন্য রাখা হয়, তাই আমরা একটি 2D অ্যারে ফিরে পেতে।

এই ফলাফলটি অ্যারের সাথে তুলনা করা আরও পরিষ্কার হতে পারে যেখানে লেবেলটি সংক্ষিপ্ত jহয় না । নীচে, বাম দিকে আপনি 3D অ্যারে দেখতে পাবেন যা লেখার ফলে আসে np.einsum('ij,jk->ijk', A, B)(যেমন আমরা লেবেল রেখেছি j):

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

সামিং অক্ষটি jডানদিকে প্রদর্শিত প্রত্যাশিত বিন্দু পণ্য দেয়।

কিছু অনুশীলন

আরও অনুভূতি পেতে einsum, সাবস্ক্রিপ্ট নোটেশন ব্যবহার করে পরিচিত নম্পপি অ্যারে ক্রিয়াকলাপগুলি প্রয়োগ করা কার্যকর হতে পারে। গুণের যোগফল এবং সংখ্যার যোগফলের সাথে যুক্ত যে কোনও কিছুই ব্যবহার করে রচনা করা যেতে পারে einsum

A এবং B একই দৈর্ঘ্যের সাথে দুটি 1D অ্যারে হওয়া যাক। উদাহরণস্বরূপ, A = np.arange(10)এবং B = np.arange(5, 15)

  • যোগফলটি Aলেখা যেতে পারে:

    np.einsum('i->', A)
  • উপাদান-ভিত্তিক গুণ,, A * Bলেখা যেতে পারে:

    np.einsum('i,i->i', A, B)
  • অভ্যন্তরীণ পণ্য বা বিন্দু পণ্য, np.inner(A, B)বা np.dot(A, B), লেখা যেতে পারে:

    np.einsum('i,i->', A, B) # or just use 'i,i'
  • বাইরের পণ্য,, np.outer(A, B)লেখা যেতে পারে:

    np.einsum('i,j->ij', A, B)

2 ডি অ্যারে Cএবং D, প্রদত্ত অক্ষগুলি সুসংগত দৈর্ঘ্য (একই দৈর্ঘ্য বা এর দুটির দৈর্ঘ্য 1) এর জন্য এখানে কয়েকটি উদাহরণ দেওয়া হয়েছে:

  • C(মূল তিরুজের যোগফল) এর ট্রেস, np.trace(C)লিখে নেওয়া যেতে পারে:

    np.einsum('ii', C)
  • মৌলিক-ভিত্তিক গুণ Cএবং এর স্থানান্তর D, এর C * D.Tলিখিত হতে পারে:

    np.einsum('ij,ji->ij', C, D)
  • Cঅ্যারের দ্বারা প্রতিটি উপাদানকে গুণমান D(একটি 4D অ্যারে করতে), C[:, :, None, None] * Dলেখা যেতে পারে:

    np.einsum('ij,kl->ijkl', C, D)  

1
খুব সুন্দর ব্যাখ্যা, ধন্যবাদ। "লক্ষ্য করুন যে আমরা আমাদের পছন্দসই আউটপুটে লেবেল হিসাবে উপস্থিত হইনি" - তাই না?
ইয়ান হিঙ্কস

ধন্যবাদ @ আইএনহিংস! এটি দেখতে টাইপোর মতো; আমি এখন এটি সংশোধন করেছি।
অ্যালেক্স রিলে

1
খুব ভাল উত্তর। এটি লক্ষ করার মতো যে ij,jkম্যাট্রিক্সের গুণটি গঠনের জন্য (তীর ছাড়া) নিজেই কাজ করতে পারে। তবে এটি স্পষ্টতার মতো বলে মনে হচ্ছে তীরগুলি এবং তারপরে আউটপুট মাত্রাগুলি রাখাই ভাল। এটি ব্লগ পোস্টে আছে।
কম্পিউটারবিজ্ঞানী

1
@ প্রশংসনীয়: এটি এমন একটি অনুষ্ঠানের যেখানে সঠিক শব্দটি বেছে নেওয়া কঠিন! আমি অনুভব করি যে "কলাম" এখানে আরও ভাল ফিট করে যেহেতু Aদৈর্ঘ্য 3, এর মধ্যে কলামগুলির দৈর্ঘ্যের সমান B(যেখানে সারিগুলির Bদৈর্ঘ্য 4 হয় এবং এটি উপাদান অনুসারে গুণিত করা যায় না A)।
অ্যালেক্স রিলি

1
নোট করুন যে বাদ দেওয়া -> শব্দার্থবিজ্ঞানের উপর প্রভাব ফেলে: "অন্তর্নিহিত মোডে, নির্বাচিত সাবস্ক্রিপ্টগুলি গুরুত্বপূর্ণ, যেহেতু আউটপুটটির অক্ষগুলি বর্ণানুক্রমিকভাবে পুনরায় সাজানো হয় This এর অর্থ এই যে এটি np.einsum('ij', a)একটি 2D অ্যারেকে প্রভাবিত করে না, যখন np.einsum('ji', a)এটি স্থানান্তরিত করে।"
বলপয়েন্টবেন

40

ধারণাটি উপলব্ধি numpy.einsum()করা খুব সহজ যদি আপনি এটি স্বজ্ঞাতভাবে বুঝতে পারেন। উদাহরণ হিসাবে, আসুন ম্যাট্রিক্সের গুণনের সাথে জড়িত একটি সাধারণ বিবরণ দিয়ে শুরু করা যাক ।


ব্যবহার করতে numpy.einsum(), আপনাকে যা করতে হবে তা হ'ল তথাকথিত সাবস্ক্রিপ্ট স্ট্রিংটিকে একটি আর্গুমেন্ট হিসাবে পাস করতে হবে , তারপরে আপনার ইনপুট অ্যারেগুলি অনুসরণ করবে ।

ধরুন আপনি দুই 2D অ্যারে আছে, যাক Aএবং B, এবং আপনি ম্যাট্রিক্স গুণ কাজ করতে চান। তুমি যা কর:

np.einsum("ij, jk -> ik", A, B)

এখানে সাবস্ক্রিপ্ট স্ট্রিং ij অ্যারের সাথে মিল রয়েছে Aযখন সাবস্ক্রিপ্ট স্ট্রিং jk অ্যারের সাথে মিলছে B। এছাড়াও, এখানে উল্লেখ করার জন্য সবচেয়ে গুরুত্বপূর্ণ বিষয়টি হ'ল প্রতিটি সাবস্ক্রিপ্ট স্ট্রিংয়ে অক্ষরের সংখ্যা অবশ্যই অ্যারের মাত্রার সাথে মেলে। (অর্থাত 2D অ্যারে, 3D অ্যারে জন্য তিনটি অক্ষর, ইত্যাদি। জন্য দুটি অক্ষর) ও আপনার মধ্যে অক্ষর পুনরাবৃত্তি যদি সাবস্ক্রিপ্ট স্ট্রিং ( jআমাদের ক্ষেত্রে), তারপর তার মানে আপনি চান einসমষ্টি যারা মাত্রা বরাবর ঘটতে। সুতরাং, তারা যোগফল হ্রাস করা হবে। (অর্থাৎ সেই মাত্রাটি চলে যাবে )

এর পরে সাবস্ক্রিপ্ট স্ট্রিংটি-> হবে আমাদের ফলাফল অ্যারে। যদি আপনি এটি খালি রেখে দেন তবে সমস্ত কিছু সংক্ষিপ্ত হয়ে যাবে এবং ফলস্বরূপ একটি স্কেলারের মান ফিরে আসবে। অন্য ফলস্বর অ্যারের সাবস্ক্রিপ্ট স্ট্রিং অনুযায়ী মাত্রা থাকবে । আমাদের উদাহরণে, এটি হবেik । এই স্বজ্ঞাত কারণ আমরা জানি ম্যাট্রিক্স গুণ জন্য অ্যারের মধ্যে কলামের সংখ্যা যে Aঅ্যারের মধ্যে সারি সংখ্যা মেলে হয়েছে B(ie গৃহস্থালির কাজ পুনরায় দ্বারা আমরা এই জ্ঞান এনকোড যা এখানে কী ঘটছে তা jমধ্যে সাবস্ক্রিপ্ট স্ট্রিং )


সংক্ষেপেnp.einsum() কিছু সাধারণ টেনসর বা এনডি-অ্যারে ক্রিয়াকলাপ বাস্তবায়নের ক্ষেত্রে ব্যবহার / শক্তি চিত্রিত করার জন্য আরও কয়েকটি উদাহরণ এখানে দেওয়া হল ।

ইনপুট

# a vector
In [197]: vec
Out[197]: array([0, 1, 2, 3])

# an array
In [198]: A
Out[198]: 
array([[11, 12, 13, 14],
       [21, 22, 23, 24],
       [31, 32, 33, 34],
       [41, 42, 43, 44]])

# another array
In [199]: B
Out[199]: 
array([[1, 1, 1, 1],
       [2, 2, 2, 2],
       [3, 3, 3, 3],
       [4, 4, 4, 4]])

1) ম্যাট্রিক্স গুণ (অনুরূপ np.matmul(arr1, arr2))

In [200]: np.einsum("ij, jk -> ik", A, B)
Out[200]: 
array([[130, 130, 130, 130],
       [230, 230, 230, 230],
       [330, 330, 330, 330],
       [430, 430, 430, 430]])

2) প্রধান তির্যক বরাবর উপাদান আহরণ (অনুরূপ np.diag(arr))

In [202]: np.einsum("ii -> i", A)
Out[202]: array([11, 22, 33, 44])

3) হাডামারড পণ্য (অর্থাত্ দুটি অ্যারের উপাদান অনুসারে পণ্য) (এর সাথে সমান arr1 * arr2)

In [203]: np.einsum("ij, ij -> ij", A, B)
Out[203]: 
array([[ 11,  12,  13,  14],
       [ 42,  44,  46,  48],
       [ 93,  96,  99, 102],
       [164, 168, 172, 176]])

4) উপাদান-ভিত্তিক স্কোয়ারিং (অনুরূপ )np.square(arr) বা এর মতো arr ** 2)

In [210]: np.einsum("ij, ij -> ij", B, B)
Out[210]: 
array([[ 1,  1,  1,  1],
       [ 4,  4,  4,  4],
       [ 9,  9,  9,  9],
       [16, 16, 16, 16]])

5) ট্রেস (অর্থাত্ মূল-তির্যক উপাদানগুলির সমষ্টি) (এর সমান np.trace(arr))

In [217]: np.einsum("ii -> ", A)
Out[217]: 110

6) ম্যাট্রিক্স ট্রান্সপোজ (অনুরূপ np.transpose(arr))

In [221]: np.einsum("ij -> ji", A)
Out[221]: 
array([[11, 21, 31, 41],
       [12, 22, 32, 42],
       [13, 23, 33, 43],
       [14, 24, 34, 44]])

)) বহিরঙ্গন পণ্য (ভেক্টরগুলির) (অনুরূপ np.outer(vec1, vec2))

In [255]: np.einsum("i, j -> ij", vec, vec)
Out[255]: 
array([[0, 0, 0, 0],
       [0, 1, 2, 3],
       [0, 2, 4, 6],
       [0, 3, 6, 9]])

8) অভ্যন্তরীণ পণ্য (ভেক্টরগুলির) (অনুরূপ np.inner(vec1, vec2))

In [256]: np.einsum("i, i -> ", vec, vec)
Out[256]: 14

9) অক্ষ 0 সহ সমষ্টি (সমান np.sum(arr, axis=0))

In [260]: np.einsum("ij -> j", B)
Out[260]: array([10, 10, 10, 10])

10) অক্ষ 1 সহ সমষ্টি (সমান np.sum(arr, axis=1))

In [261]: np.einsum("ij -> i", B)
Out[261]: array([ 4,  8, 12, 16])

11) ব্যাচ ম্যাট্রিক্স গুণ

In [287]: BM = np.stack((A, B), axis=0)

In [288]: BM
Out[288]: 
array([[[11, 12, 13, 14],
        [21, 22, 23, 24],
        [31, 32, 33, 34],
        [41, 42, 43, 44]],

       [[ 1,  1,  1,  1],
        [ 2,  2,  2,  2],
        [ 3,  3,  3,  3],
        [ 4,  4,  4,  4]]])

In [289]: BM.shape
Out[289]: (2, 4, 4)

# batch matrix multiply using einsum
In [292]: BMM = np.einsum("bij, bjk -> bik", BM, BM)

In [293]: BMM
Out[293]: 
array([[[1350, 1400, 1450, 1500],
        [2390, 2480, 2570, 2660],
        [3430, 3560, 3690, 3820],
        [4470, 4640, 4810, 4980]],

       [[  10,   10,   10,   10],
        [  20,   20,   20,   20],
        [  30,   30,   30,   30],
        [  40,   40,   40,   40]]])

In [294]: BMM.shape
Out[294]: (2, 4, 4)

12) অক্ষ বরাবর যোগফল 2 (সমান np.sum(arr, axis=2))

In [330]: np.einsum("ijk -> ij", BM)
Out[330]: 
array([[ 50,  90, 130, 170],
       [  4,   8,  12,  16]])

13) অ্যারেতে সমস্ত উপাদানগুলির সমষ্টি (সমান)np.sum(arr) )

In [335]: np.einsum("ijk -> ", BM)
Out[335]: 480

14) একাধিক অক্ষ (অর্থাত্ প্রান্তিককরণ) এর সমষ্টি
(সমানnp.sum(arr, axis=(axis0, axis1, axis2, axis3, axis4, axis6, axis7)) )

# 8D array
In [354]: R = np.random.standard_normal((3,5,4,6,8,2,7,9))

# marginalize out axis 5 (i.e. "n" here)
In [363]: esum = np.einsum("ijklmnop -> n", R)

# marginalize out axis 5 (i.e. sum over rest of the axes)
In [364]: nsum = np.sum(R, axis=(0,1,2,3,4,6,7))

In [365]: np.allclose(esum, nsum)
Out[365]: True

15) ডাবল ডট পণ্য ( এনপি.সামের অনুরূপ (হাদামার্ড-পণ্য) সিএফ. 3 )

In [772]: A
Out[772]: 
array([[1, 2, 3],
       [4, 2, 2],
       [2, 3, 4]])

In [773]: B
Out[773]: 
array([[1, 4, 7],
       [2, 5, 8],
       [3, 6, 9]])

In [774]: np.einsum("ij, ij -> ", A, B)
Out[774]: 124

16) 2 ডি এবং 3 ডি অ্যারের গুণ

সমীকরণের রৈখিক সিস্টেমটি সমাধান করার সময় এই জাতীয় গুণটি খুব কার্যকর হতে পারে ( এক্স = খ ) যেখানে আপনি ফলাফল যাচাই করতে চান।

# inputs
In [115]: A = np.random.rand(3,3)
In [116]: b = np.random.rand(3, 4, 5)

# solve for x
In [117]: x = np.linalg.solve(A, b.reshape(b.shape[0], -1)).reshape(b.shape)

# 2D and 3D array multiplication :)
In [118]: Ax = np.einsum('ij, jkl', A, x)

# indeed the same!
In [119]: np.allclose(Ax, b)
Out[119]: True

বিপরীতে, যদি np.matmul()এই যাচাইকরণের জন্য কাউকে ব্যবহার করতে হয় তবে আমাদের কয়েকটি করতে হবেreshape করতে হয় তবে একই ফলাফলটি অর্জন করতে আমাদের বেশ অপারেশন করতে হবে যেমন:

# reshape 3D array `x` to 2D, perform matmul
# then reshape the resultant array to 3D
In [123]: Ax_matmul = np.matmul(A, x.reshape(x.shape[0], -1)).reshape(x.shape)

# indeed correct!
In [124]: np.allclose(Ax, Ax_matmul)
Out[124]: True

বোনাস : আরও গণিত এখানে পড়ুন: আইনস্টাইন-সমীকরণ এবং স্পষ্টভাবে এখানে: টেনসর-স্বরলিপি


7

তাদের ইন্টারপ্লে হাইলাইট করার জন্য বিভিন্ন, তবে সুসংগত মাত্রা সহ 2 টি অ্যারে তৈরি করা যাক

In [43]: A=np.arange(6).reshape(2,3)
Out[43]: 
array([[0, 1, 2],
       [3, 4, 5]])


In [44]: B=np.arange(12).reshape(3,4)
Out[44]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

আপনার গণনা, একটি (4,2) অ্যারে উত্পাদন করতে একটি (3,4) সহ একটি (2,3) এর একটি 'ডট' (পণ্যের যোগফল) নেয়। iএর 1 ম मंद A, শেষের C; kসর্বশেষ B, 1 ম Cjসমষ্টি দ্বারা 'গ্রাস' হয়।

In [45]: C=np.einsum('ij,jk->ki',A,B)
Out[45]: 
array([[20, 56],
       [23, 68],
       [26, 80],
       [29, 92]])

এটি হ'ল এটি np.dot(A,B).T- এটি চূড়ান্ত আউটপুট যা স্থানান্তরিত হয়।

কী হয় তার আরও দেখতে j, Cসাবস্ক্রিপ্টগুলিকে এতে পরিবর্তন করুন ijk:

In [46]: np.einsum('ij,jk->ijk',A,B)
Out[46]: 
array([[[ 0,  0,  0,  0],
        [ 4,  5,  6,  7],
        [16, 18, 20, 22]],

       [[ 0,  3,  6,  9],
        [16, 20, 24, 28],
        [40, 45, 50, 55]]])

এটি এর সাথেও উত্পাদিত হতে পারে:

A[:,:,None]*B[None,:,:]

এটি হ'ল, kশেষের দিকে একটি মাত্রা যুক্ত করুন Aএবং iসামনের দিকে একটি যুক্ত করুন B, যার ফলে একটি (2,3,4) অ্যারে হবে।

0 + 4 + 16 = 20, 9 + 28 + 55 = 92ইত্যাদি; jপূর্বের ফলাফল পেতে যোগ করুন এবং স্থানান্তর করুন:

np.sum(A[:,:,None] * B[None,:,:], axis=1).T

# C[k,i] = sum(j) A[i,j (,k) ] * B[(i,)  j,k]

6

আমি নম্পপি পেয়েছি : ব্যবসায়ের কৌশলগুলি (দ্বিতীয় খণ্ড) নির্দেশমূলক

আউটপুট অ্যারের ক্রমটি নির্দেশ করতে আমরা -> ব্যবহার করি। সুতরাং 'আইজ, আই-> জ' কে বাম হাতের পাশ (এলএইচএস) এবং ডান হাতের দিক (আরএইচএস) হিসাবে মনে করুন। এলএইচএসে লেবেলের যে কোনও পুনরাবৃত্তি পণ্য উপাদান হিসাবে গণনা করে তার পরে যোগফল দেয়। আরএইচএস (আউটপুট) দিকে লেবেল পরিবর্তন করে আমরা অক্ষটি সংজ্ঞায়িত করতে পারি যে আমরা ইনপুট অ্যারে, অর্থাৎ অক্ষ 0, 1 এবং আরও বরাবর যোগফলের সাথে সম্মতি নিয়ে এগিয়ে যেতে চাই।

import numpy as np

>>> a
array([[1, 1, 1],
       [2, 2, 2],
       [3, 3, 3]])
>>> b
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> d = np.einsum('ij, jk->ki', a, b)

লক্ষ করুন যে তিনটি অক্ষ আছে, i, j, k, এবং সেই জে পুনরাবৃত্তি হয় (বাম-হাতের দিকে)। i,jজন্য সারি এবং কলাম উপস্থাপন aj,kজন্য b

পণ্যটি গণনা করতে এবং jঅক্ষটি সারিবদ্ধ করার জন্য আমাদের একটি অক্ষ যুক্ত করতে হবে a। ( bপ্রথম অক্ষের সাথে সম্প্রচারিত হবে (?)

a[i, j, k]
   b[j, k]

>>> c = a[:,:,np.newaxis] * b
>>> c
array([[[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8]],

       [[ 0,  2,  4],
        [ 6,  8, 10],
        [12, 14, 16]],

       [[ 0,  3,  6],
        [ 9, 12, 15],
        [18, 21, 24]]])

jডানদিক থেকে অনুপস্থিত তাই j3x3x3 অ্যারের দ্বিতীয় অক্ষটি আমরা সমষ্টিটি যোগ করি

>>> c = c.sum(1)
>>> c
array([[ 9, 12, 15],
       [18, 24, 30],
       [27, 36, 45]])

অবশেষে, সূচকগুলি (বর্ণানুক্রমিকভাবে) ডান দিকে বিপরীত হয় যাতে আমরা স্থানান্তর করি।

>>> c.T
array([[ 9, 18, 27],
       [12, 24, 36],
       [15, 30, 45]])

>>> np.einsum('ij, jk->ki', a, b)
array([[ 9, 18, 27],
       [12, 24, 36],
       [15, 30, 45]])
>>>

নম্পপি: ব্যবসায়ের কৌশলগুলি (দ্বিতীয় খণ্ড) সাইটের মালিকের পাশাপাশি একটি ওয়ার্ডপ্রেস অ্যাকাউন্টের একটি আমন্ত্রণের প্রয়োজন বলে মনে হচ্ছে
তেজস শেট্টি

... আপডেট হওয়া লিঙ্ক, ভাগ্যক্রমে আমি এটি একটি অনুসন্ধানের সাথে খুঁজে পেয়েছি। - Thnx
wwii

@ টেজাসেটি এখন এখানে আরও অনেক ভাল উত্তর - সম্ভবত আমার এটি মুছে ফেলা উচিত।
wwii

2
দয়া করে আপনার উত্তর মুছবেন না।
তেজাস শেঠি

4

আইন সমীকরণগুলি পড়ার সময়, আমি কেবল তাদের প্রয়োজনীয় সংস্করণগুলিতে মানসিকভাবে সেদ্ধ করতে সক্ষম হওয়া সবচেয়ে সহায়ক বলে মনে করেছি।

নীচের (চাপিয়ে দেওয়া) বিবৃতি দিয়ে শুরু করা যাক:

C = np.einsum('bhwi,bhwj->bij', A, B)

বিরামচিহ্নের মধ্য দিয়ে কাজ করার আগে আমরা দেখতে পাই যে আমাদের কাছে দুটি 4-বর্ণের কমা-বিচ্ছিন্ন ব্লব রয়েছে - bhwiএবং bhwj, তীরের আগে, এবং এর পরে একটি একক 3-অক্ষর প্রস্ফুটিত bijহয়। অতএব, সমীকরণটি দুটি র‌্যাঙ্ক -4 টেনসর ইনপুট থেকে একটি র‌্যাঙ্ক -3 টেনসর ফলাফল তৈরি করে।

এখন, প্রতিটি ব্লকের প্রতিটি অক্ষরকে একটি পরিসীমা পরিবর্তকের নাম দেওয়া উচিত। চিঠিটি ব্লবটিতে যে অবস্থানটিতে উপস্থিত হয় তা হ'ল অক্ষরটির সূচক যা এটি t টেনসরটিতে বিস্তৃত। অত্যাবশ্যক সংক্ষিপ্তসার যা সি এর প্রতিটি উপাদান উত্পাদন করে, তাই লুপের জন্য তিনটি নেস্টেড দিয়ে শুরু করতে হবে, সি এর প্রতিটি সূচকের জন্য একটি ested

for b in range(...):
    for i in range(...):
        for j in range(...):
            # the variables b, i and j index C in the order of their appearance in the equation
            C[b, i, j] = ...

সুতরাং, মূলত, আপনার forসি এর প্রতিটি আউটপুট সূচকের জন্য একটি লুপ রয়েছে now আমরা আপাতত নির্ধারিত রেঞ্জগুলি ছাড়ব।

পরবর্তী আমরা বাম দিকে তাকান - সেখানে যে কোন পরিসীমা ভেরিয়েবল না প্রদর্শিত ডানদিকের সাইড? আমাদের ক্ষেত্রে - হ্যাঁ, hএবং w। এই forজাতীয় প্রতিটি পরিবর্তনশীলগুলির জন্য একটি অভ্যন্তরীণ নেস্টেড লুপ যুক্ত করুন:

for b in range(...):
    for i in range(...):
        for j in range(...):
            C[b, i, j] = 0
            for h in range(...):
                for w in range(...):
                    ...

অন্তঃস্থলীয় লুপের অভ্যন্তরে আমরা এখন সমস্ত সূচকগুলি সংজ্ঞায়িত করেছি, সুতরাং আমরা আসল সংক্ষেপটি লিখতে পারি এবং অনুবাদটি সম্পূর্ণ হয়:

# three nested for-loops that index the elements of C
for b in range(...):
    for i in range(...):
        for j in range(...):

            # prepare to sum
            C[b, i, j] = 0

            # two nested for-loops for the two indexes that don't appear on the right-hand side
            for h in range(...):
                for w in range(...):
                    # Sum! Compare the statement below with the original einsum formula
                    # 'bhwi,bhwj->bij'

                    C[b, i, j] += A[b, h, w, i] * B[b, h, w, j]

আপনি যদি এখন পর্যন্ত কোডটি অনুসরণ করতে সক্ষম হন তবে অভিনন্দন! আইনসম্মত সমীকরণগুলি পড়তে আপনার যা প্রয়োজন তা এই। বিশেষভাবে লক্ষ করুন যে কীভাবে মূল আইনসূত্র সূত্রটি উপরের স্নিপেটে চূড়ান্ত সমষ্টি বিবৃতিতে মানচিত্র করে। লুপস এবং রেঞ্জের সীমাগুলি কেবল ফ্লফ এবং সেই চূড়ান্ত বিবৃতিটি যা যা ঘটছে তা বুঝতে আপনার সত্যই দরকার।

সম্পূর্ণতার স্বার্থে, আসুন আমরা প্রতিটি বিস্তৃত চলকের জন্য ব্যাপ্তি নির্ধারণ করতে দেখি। ভাল, প্রতিটি ভেরিয়েবলের ব্যাপ্তি কেবলমাত্র মাত্রা (গুলি) এর দৈর্ঘ্য যা এটি সূচক করে। স্পষ্টতই, যদি কোনও ভেরিয়েবল এক বা একাধিক টেনসরগুলিতে একাধিক মাত্রার সূচক করে তবে those প্রতিটি মাত্রার দৈর্ঘ্য সমান হতে হবে। সম্পূর্ণ রেঞ্জের সাথে উপরের কোডটি এখানে:

# C's shape is determined by the shapes of the inputs
# b indexes both A and B, so its range can come from either A.shape or B.shape
# i indexes only A, so its range can only come from A.shape, the same is true for j and B
assert A.shape[0] == B.shape[0]
assert A.shape[1] == B.shape[1]
assert A.shape[2] == B.shape[2]
C = np.zeros((A.shape[0], A.shape[3], B.shape[3]))
for b in range(A.shape[0]): # b indexes both A and B, or B.shape[0], which must be the same
    for i in range(A.shape[3]):
        for j in range(B.shape[3]):
            # h and w can come from either A or B
            for h in range(A.shape[1]):
                for w in range(A.shape[2]):
                    C[b, i, j] += A[b, h, w, i] * B[b, h, w, j]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.