একটি অদ্ভুত অ্যারে জুড়ে গুণ


89

আমি 2D অ্যারেতে প্রতিটি পদ 1 1 অ্যারেতে সংশ্লিষ্ট পদগুলি দ্বারা গুণ করার চেষ্টা করছি। নাম্পি.মલ્ટ্টিপ্লাই ফাংশন হিসাবে দেখানো হয়েছে আমি যদি প্রতিটি কলাম 1D অ্যারে দ্বারা গুণ করতে চাই তবে এটি খুব সহজ । তবে আমি বিপরীতটি করতে চাই, প্রতিটি শব্দকে একের পর এক গুণ করব ly অন্য কথায় আমি গুণ করতে চাই:

[1,2,3]   [0]
[4,5,6] * [1]
[7,8,9]   [2]

এবং পেতে

[0,0,0]
[4,5,6]
[14,16,18]

পরিবর্তে আমি পেতে

[0,2,6]
[0,5,12]
[0,8,18]

কেউ কি জানে যে নাম্পি দিয়ে এটি করার কোনও মার্জিত উপায় আছে? অ্যালেক্স অনেক অনেক ধন্যবাদ


4
আহ আমি যেমন প্রশ্ন জমা দিয়েছিলাম ঠিক তেমনই তা বের করে ফেলেছি। প্রথমে বর্গ ম্যাট্রিক্স স্থানান্তর করুন, গুণ করুন, তারপরে উত্তরটি স্থানান্তর করুন।
অ্যালেক্স এস

সারিটি একটি কলাম ম্যাট্রিক্সে স্থানান্তর করা ভাল তবে আপনাকে উত্তরটি পুনরায় স্থানান্তর করতে হবে না। আপনি A * Bযদি A * B[...,None]এমনটি করতে চান যা Bকোনও নতুন অক্ষ ( None) যোগ করে ট্রান্সফেস করে ।
জিজ্ঞাসা

ধন্যবাদ, এটা সত্য। সমস্যাটি যখন তখন আপনার 1D অ্যারে কল করা থাকে .টানস্পোজ করুন () বা .T এটি এটিকে একটি কলাম অ্যারে রূপান্তরিত করে না, এটি একটি সারি হিসাবে রেখে দেয়, আমি যতদূর জানি যে আপনি এটি একটি কলাম হিসাবে সংজ্ঞায়িত করতে হবে ঠিক ব্যাট হতে. পছন্দ x = [[1],[2],[3]]বা কিছু।
অ্যালেক্স এস

উত্তর:


119

আপনি যেমন দেখিয়েছেন তেমন সাধারণ গুণ:

>>> import numpy as np
>>> m = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> c = np.array([0,1,2])
>>> m * c
array([[ 0,  2,  6],
       [ 0,  5, 12],
       [ 0,  8, 18]])

আপনি যদি একটি অক্ষর যোগ করেন তবে এটি আপনার পছন্দমতো গুন বাড়িয়ে তুলবে:

>>> m * c[:, np.newaxis]
array([[ 0,  0,  0],
       [ 4,  5,  6],
       [14, 16, 18]])

আপনি দু'বার স্থানান্তর করতে পারেন:

>>> (m.T * c).T
array([[ 0,  0,  0],
       [ 4,  5,  6],
       [14, 16, 18]])

নতুন অক্ষ পদ্ধতির সাহায্যে দুটি 1D অ্যারে গুণ করা এবং 2D অ্যারে তৈরি করা সম্ভব। যেমন [a,b] op [c,d] -> [[a*c, b*c], [a*d, b*d]]
কন সাইক

50

আমি গতির জন্য বিভিন্ন বিকল্পের তুলনা করেছি এবং এটি পেয়েছি - আমার আশ্চর্যের অনেক বেশি - সমস্ত বিকল্প (বাদে diag) সমান দ্রুত। আমি ব্যক্তিগতভাবে ব্যবহার

A * b[:, None]

(বা (A.T * b).T) কারণ এটি সংক্ষিপ্ত।

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


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

import numpy
import perfplot


def newaxis(data):
    A, b = data
    return A * b[:, numpy.newaxis]


def none(data):
    A, b = data
    return A * b[:, None]


def double_transpose(data):
    A, b = data
    return (A.T * b).T


def double_transpose_contiguous(data):
    A, b = data
    return numpy.ascontiguousarray((A.T * b).T)


def diag_dot(data):
    A, b = data
    return numpy.dot(numpy.diag(b), A)


def einsum(data):
    A, b = data
    return numpy.einsum("ij,i->ij", A, b)


perfplot.save(
    "p.png",
    setup=lambda n: (numpy.random.rand(n, n), numpy.random.rand(n)),
    kernels=[
        newaxis,
        none,
        double_transpose,
        double_transpose_contiguous,
        diag_dot,
        einsum,
    ],
    n_range=[2 ** k for k in range(13)],
    xlabel="len(A), len(b)",
)

4
প্লটের জন্য কোড সরবরাহ করে দুর্দান্ত স্পর্শ। ধন্যবাদ
rocksNwaves

17

আপনি ম্যাট্রিক্স গুণন (ওরফে ডট পণ্য) ব্যবহার করতে পারেন:

a = [[1,2,3],[4,5,6],[7,8,9]]
b = [0,1,2]
c = numpy.diag(b)

numpy.dot(c,a)

যা আরও মার্জিত তা সম্ভবত স্বাদের বিষয়।


4
চমৎকার, +1, সে সম্পর্কে
ভাবেননি

10
dotসত্যিই এখানে overkill হয়। আপনি কেবল 0 দ্বারা অপ্রয়োজনীয় গুণ এবং 0 তে সংযোজন করছেন
দ্বি রিকো

4
আপনি যদি কোনও এনএক্সএল ভেক্টরকে কোনও এনএক্সডি ম্যাট্রিক্সে মাল্টিপী করতে চান যেখানে d n এর চেয়ে বড় হয় মেমরির সমস্যাগুলিও এটি ট্রিগার করতে পারে।
জোনাসন

এটিকে নিম্নগামী হিসাবে ঘন ম্যাট্রিক্স তৈরি করার সময় ধীর এবং প্রচুর স্মৃতি ব্যবহার করে uses diag
নিকো Schlömer

16

তবুও অন্য কৌশল (v1.6 হিসাবে)

A=np.arange(1,10).reshape(3,3)
b=np.arange(3)

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

আমি নাম্বার ব্রডকাস্টিং ( newaxis) এর সাথে দক্ষ , তবে আমি এখনও এই নতুন einsumসরঞ্জামটির চারপাশে আমার পথ সন্ধান করছি । সুতরাং আমি এই সমাধানটি খুঁজতে কিছুটা খেলা করেছি।

সময় (আইপথন সময়কাল ব্যবহার করে):

einsum: 4.9 micro
transpose: 8.1 micro
newaxis: 8.35 micro
dot-diag: 10.5 micro

উল্লেখ্য, একটি পরিবর্তন iকরার জন্য j, np.einsum('ij,j->ij',A,b), ম্যাট্রিক্স যে অ্যালেক্স চায় না উৎপন্ন হয়। এবং np.einsum('ji,j->ji',A,b)কার্যত ডাবল ট্রান্সপোজ করে।


4
আপনি যদি কম্পিউটারে এই সময়টিতে এত বড় হন যে এটি কমপক্ষে কয়েক মিলি সেকেন্ড নেয় এবং আপনার প্রাসঙ্গিক সিস্টেমের তথ্যের সাথে ফলাফলগুলি এখানে পোস্ট করে তবে এটি প্রশংসিত হবে।
ড্যানিয়েল

4
বৃহত্তর অ্যারে (100x100) দিয়ে আপেক্ষিক সংখ্যাগুলি প্রায় সমান। einsumm(25 মাইক্রো) অন্যের চেয়ে দ্বিগুণ দ্রুত (ডট-ডায়াগ আরও ধীর করে দেয়)। এটি এনপি 1.7, 'লিবাটলাস 3 জিএফ-সিএস 2' এবং 'লিবাটলাস-বেস-দেব' (উবুন্টু 10.4, একক প্রসেসর) এর সাথে নতুনভাবে সংকলিত। timeit10000 লুপের সেরা দেয়।
এইচপিএলজে

4
এটি দুর্দান্ত উত্তর এবং আমি মনে করি এটিই একমাত্র গ্রহণ করা উচিত ছিল। যাইহোক, উপরে লিখিত কোডটি আসলে ম্যাট্রিক্সকে দেয় অ্যালেক্স এড়াতে চাইছিল (আমার মেশিনে)। এইচএপলজ যেটি ভুল বলেছেন তা আসলে সঠিক right
ইয়ার দাওন

সময়গুলি এখানে বিভ্রান্ত করছে। ডট-ডায়াগ অন্যান্য তিনটি বিকল্পের চেয়ে সত্যই খারাপ এবং আইনসাম অন্যগুলির চেয়ে দ্রুত নয়।
নিকো শ্ল্যামার

@ নিকোস্ক্ল্যামার, আমার উত্তরটি প্রায় 5 বছর পুরানো, এবং অনেকগুলি numpyসংস্করণ ফিরে।
এইচপলজ

1

গুগলে হারিয়ে যাওয়া আত্মাদের জন্য, numpy.expand_dimsতখন ব্যবহার করা কার্যকর numpy.repeatহবে এবং উচ্চতর মাত্রিক ক্ষেত্রে (যেমন একটি আকারকে (10, 12, 3) একটি (10, 12) দ্বারা গুণিত করবে)।

>>> import numpy
>>> a = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
>>> b = numpy.array([0,1,2])
>>> b0 = numpy.expand_dims(b, axis = 0)
>>> b0 = numpy.repeat(b0, a.shape[0], axis = 0)
>>> b1 = numpy.expand_dims(b, axis = 1)
>>> b1 = numpy.repeat(b1, a.shape[1], axis = 1)
>>> a*b0
array([[ 0,  2,  6],
   [ 0,  5, 12],
   [ 0,  8, 18]])
>>> a*b1
array([[ 0,  0,  0],
   [ 4,  5,  6],
   [14, 16, 18]])

-4

কেন আপনি শুধু না

>>> m = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> c = np.array([0,1,2])
>>> (m.T * c).T

??


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