วิธีที่รวดเร็ว / มีประสิทธิภาพในการแยกค่าสัมประสิทธิ์ตัวกรอง 2D จำนวนเต็มแยกได้


21

ฉันต้องการที่จะสามารถตรวจสอบได้อย่างรวดเร็วว่าเคอร์เนล 2 มิติของค่าสัมประสิทธิ์จำนวนเต็มแบ่งออกเป็นสอง 1D เมล็ดที่มีสัมประสิทธิ์จำนวนเต็ม เช่น

 2   3   2
 4   6   4
 2   3   2

สามารถแยกออกเป็น

 2   3   2

และ

 1
 2
 1

การทดสอบความสามารถแยกได้จริงดูเหมือนจะค่อนข้างตรงไปตรงมาโดยใช้เลขคณิตจำนวนเต็ม แต่การแยกย่อยเป็นฟิลเตอร์ 1D ที่มีค่าสัมประสิทธิ์จำนวนเต็มกำลังพิสูจน์ว่าเป็นปัญหาที่ยากขึ้น ความยากลำบากดูเหมือนจะอยู่ในความจริงที่ว่าอัตราส่วนระหว่างแถวหรือคอลัมน์อาจไม่ใช่จำนวนเต็ม (เศษส่วนที่มีเหตุผล) เช่นในตัวอย่างข้างต้นเรามีอัตราส่วน 2, 1/2, 3/2 และ 2/3

ฉันไม่ต้องการใช้วิธีการที่หนักเช่น SVD เพราะ (ก) มันค่อนข้างแพงสำหรับความต้องการของฉันและ (b) มันก็ไม่ได้ช่วยในการกำหนดสัมประสิทธิ์จำนวนเต็ม

ความคิดใด ๆ


ข้อมูลเพิ่มเติม

ค่าสัมประสิทธิ์อาจเป็นค่าบวกลบหรือเป็นศูนย์และอาจมีกรณีทางพยาธิวิทยาที่ผลรวมของเวกเตอร์ 1D หรือทั้งคู่เป็นศูนย์เช่น

-1   2  -1
 0   0   0
 1  -2   1

สามารถแยกออกเป็น

 1  -2   1

และ

-1
 0
 1

1
ฉันจำได้ว่าพยายามคิดวิธีนี้ในวิทยาลัย ฉันเกือบจะประสบความสำเร็จ แต่ฉันจำไม่ได้ว่า =) ฉันหยุดคิดไม่ได้ตอนนี้ที่คุณพูดถึงมัน!
Phonon

@Phonon: เฮ้ - คิดให้ดี - ฉันใช้แรงบันดาลใจกับอันนี้ได้ ;-)
Paul R

เป็นไปได้ไหมที่จะทำสิ่งเดียวกัน แต่ใช้สองค่าหรือค่าลอย?
Diego Catalano

@DiegoCatalano: ดูคำตอบของเดนิสด้านล่างและคำถามที่เขาเชื่อมโยงไปยัง math.stackexchange.com - ฉันคิดว่ามันอาจใช้กับกรณีทั่วไปมากขึ้นของค่าสัมประสิทธิ์จุดลอยตัว
Paul R

@ พอลเราจะติดต่อคุณทางอีเมลได้อย่างไร? ขอขอบคุณ.
Royi

คำตอบ:


11

ฉันได้@Phononรับคำตอบและแก้ไขมันบ้างเพื่อที่จะใช้วิธี GCD ในคอลัมน์ด้านบนและคอลัมน์ซ้ายแทนที่จะเป็นผลรวมของแถว / คอลัมน์ ดูเหมือนว่าจะจัดการกับกรณีทางพยาธิวิทยาได้ดีขึ้นเล็กน้อย มันยังคงล้มเหลวหากแถวบนสุดหรือคอลัมน์ซ้ายเป็นศูนย์ทั้งหมด แต่กรณีเหล่านี้สามารถตรวจสอบได้ก่อนที่จะใช้วิธีนี้

function [X, Y, valid] = separate(M)    % separate 2D kernel M into X and Y vectors 
  X = M(1, :);                          % init X = top row of M
  Y = M(:, 1);                          % init Y = left column of M
  nx = numel(X);                        % nx = no of columns in M
  ny = numel(Y);                        % ny = no of rows in M
  gx = X(1);                            % gx = GCD of top row
  for i = 2:nx
    gx = gcd(gx, X(i));
  end
  gy = Y(1);                            % gy = GCD of left column
  for i = 2:ny
    gy = gcd(gy, Y(i));
  end
  X = X / gx;                           % scale X by GCD of X
  Y = Y / gy;                           % scale Y by GCD of Y
  scale = M(1, 1) / (X(1) * Y(1));      % calculate scale factor
  X = X * scale;                        % apply scale factor to X
  valid = all(all((M == Y * X)));       % result valid if we get back our original M
end

ขอบคุณมาก@Phononและ@Jason Rสำหรับแนวคิดดั้งเดิมสำหรับสิ่งนี้


10

เข้าใจแล้ว! โพสต์รหัส MATLAB จะโพสต์คำอธิบายในคืนนี้หรือพรุ่งนี้

% Two original arrays
N = 3;
range = 800;
a = round( range*(rand(N,1)-0.5) )
b = round( range*(rand(1,N)-0.5) )

% Create a matrix;
M = a*b;
N = size(M,1);

% Sanity check
disp([num2str(rank(M)) ' <- this should be 1!']);

% Sum across rows and columns
Sa = M * ones(N,1);
Sb = ones(1,N) * M;

% Get rid of zeros
SSa = Sa( Sa~=0 );
SSb = Sb( Sb~=0 );

if isempty(SSa) | isempty(SSb)
    break;
end

% Sizes of array without zeros
Na = numel(SSa);
Nb = numel(SSb);

% Find Greatest Common Divisor of Sa and Sb.
Ga = SSa(1);
Gb = SSb(1);

for l=2:Na
    Ga = gcd(Ga,SSa(l));
end

for l=2:Nb
    Gb = gcd(Gb,SSb(l));
end

%Divide by the greatest common divisor
Sa = Sa / Ga;
Sb = Sb / Gb;

%Scale one of the vectors
MM = Sa * Sb;
Sa = Sa * (MM(1) / M(1));

disp('Two arrays found:')
Sa
Sb
disp('Sa * Sb = ');
Sa*Sb
disp('Original = ');
M

ขอบคุณ - นี่เยี่ยมมาก - ฉันนอนหลับอยู่เมื่อคืนที่ผ่านมาคิดเกี่ยวกับการแยกแยะสัมประสิทธิ์และอื่น ๆ แต่ใช้ GCD แบบนี้ง่ายกว่าและหรูหรากว่ามาก แต่น่าเสียดายที่ยังคงเป็นหนึ่งริ้วรอยเหล็กออก - A=[-2 1 0 -1 2]; B=[2 -3 6 0 -1]; M=A'*B;จะต้องมีการทำงานร่วมกับทั้งค่าสัมประสิทธิ์เชิงบวกและเชิงลบและนี้สามารถนำไปสู่กรณีเลวเช่น ปัญหาตรงนี้ก็เป็นsum(A) = 0เช่นSb = [0 0 0 0 0]นั้น ฉันจะลองปรับเปลี่ยนอัลกอริทึมของคุณเพื่อที่จะใช้ผลรวมของค่าสัมบูรณ์ของสัมประสิทธิ์และดูว่าช่วยได้ไหม ขอบคุณอีกครั้งสำหรับความช่วยเหลือของคุณ
Paul R

OK - ดูเหมือนว่าคุณยังสามารถได้รับ GCDs และทำปรับโดยใช้abs(M)คือSa=abs(M)*ones(N,1); Sb=ones(1,N)*abs(M);แล้วยังคงเป็นข้างต้น แต่ผมยังไม่สามารถดูวิธีการเรียกคืนป้ายบอกทางไปSa, Sbที่สิ้นสุด ฉันได้เพิ่มตัวอย่างทางพยาธิวิทยาที่แสดงให้เห็นปัญหาในคำถามเดิมข้างต้น
Paul R

ฉันคิดว่าฉันมีวิธีแก้ปัญหาการทำงานในขณะนี้ - ฉันโพสต์ไว้เป็นคำตอบที่แยกต่างหาก แต่เครดิตจะส่งถึงคุณสำหรับแนวคิดพื้นฐาน ขอบคุณอีกครั้ง !
Paul R

7

บางทีฉันอาจจะทำให้ปัญหาเล็กน้อย แต่ดูเหมือนว่าคุณจะทำได้:

  • ยังไม่มีข้อความMAaผมผม=0,1,...,ยังไม่มีข้อความ-1
  • J>0

    • aJa0JRJ
    • RJ
    • RJaJa0J0x
    • aJa0
  • x

xk,nโอRม.=xkนาทีผม=0ยังไม่มีข้อความ-1xผม
  • xnโอRม.
    xsaล.อีd=KxnโอRม.,K=1,2,...,M
    KM

ไม่ใช่วิธีที่สง่างามที่สุดและเป็นไปได้ว่ามันมีวิธีที่ดีกว่า แต่ควรใช้งานได้ค่อนข้างง่ายในการติดตั้งและควรมีความรวดเร็วสำหรับเมทริกซ์ขนาดปานกลาง


ขอบคุณ - ฉันคิดว่าฉันอาจจะมุ่งไปในทิศทางนี้ก่อนที่ฉันจะจมลงในรายละเอียด ฉันยังไม่ชัดเจน 100% ว่าคุณจะได้รับวิธีแก้ปัญหาด้วยวิธีนี้เสมอ แต่อย่างไรก็ตามฉันควรจะเขียนโค้ดนี้ขึ้นมาและลองด้วยตัวอย่างเล็ก ๆ น้อย ๆ ฉันมีลางสังหรณ์ว่าอาจจำเป็นต้องใช้ทั้งแถวที่ชาญฉลาดและคอลัมน์ที่ฉลาดเพื่อดูว่าโซลูชันใดที่ให้ผลดีที่สุด ขอขอบคุณที่สละเวลาอ่านรายละเอียด - ฉันจะยุ่งกับมันและแจ้งให้คุณทราบว่ามันทำงานอย่างไร
Paul R

คุณไม่พบตัวหารร่วมที่ยิ่งใหญ่ที่สุดขององค์ประกอบแรกของแถวและใช้เพื่อกำหนดเวกเตอร์พื้นฐานของคุณหรือไม่
Jim Clay

@JimClay: ใช่นั่นคือสิ่งที่คุณกำลังทำในตอนท้ายถ้าคุณมีฟังก์ชั่นการใช้งาน
Jason R

3

xYZA|A-xYZ|
x Y Z
YZxx Y Z x Y Z ... ในทางกลับกัน

(จากการประมาณ -a -convolution-as-a-sum-of-convolutions แยกกันได้บน math.stackexchange)


1
พยายามอย่าตอบคำถามด้วยลิงค์ที่ไม่ได้อธิบาย เป็นการดีกว่าที่จะอธิบายรายละเอียดที่จำเป็นในคำตอบของคุณและรวมลิงค์ไว้เพื่ออ้างอิงเท่านั้น ด้วยวิธีนี้หากลิงก์แบ่งรายละเอียดที่สำคัญของคำตอบนั้นยังคงอยู่
Sam Maloney

@ SamMaloney: ฉันเห็นเหตุผลว่าทำไมไม่จำเป็น ลิงค์อธิบายทุกอย่างในรายละเอียด มันจะยังคงปรากฏขึ้นในการค้นหาคำถาม & ดังนั้นทำไมไม่
Naresh

1
@Naresh ฉันเพียงกล่าวถึงเพราะหนึ่งในเป้าหมายของเว็บไซต์แลกเปลี่ยนแลกเปลี่ยนคือการสร้างพื้นที่เก็บข้อมูลของคำถามที่ตอบสำหรับการอ้างอิงในอนาคต ดังนั้นในขณะที่ฉันเข้าใจว่าลิงก์นี้เป็นของไซต์ SE อื่นและควรจะค่อนข้างปลอดภัย แต่เป็นแนวปฏิบัติทั่วไปที่ดีที่สุดที่จะไม่นับลิงก์ที่ยังคงใช้งานได้หลายปีนับจากนี้ . ให้ร่างทั่วไปของเหล่านี้ "สองวิธีง่ายในคำตอบที่จะให้แน่ใจว่าข้อมูลจะถูกเก็บไว้แม้ว่าบางสิ่งบางอย่างเกิดขึ้นกับคำถามที่เชื่อมโยงที่ผมกล่าวว่าแม้ว่านี้ได้มากขึ้นจากความคิดเห็นทั่วไปเกี่ยวกับการปฏิบัติที่ดีที่สุดเกี่ยวกับการเชื่อมโยงในคำตอบ.
Sam Maloney
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.