ขั้นตอนวิธีการเลี้ยงค็อกเทล SVD การใช้งาน ... ในบรรทัดเดียวของรหัส?


89

ในสไลด์ภายในการบรรยายเบื้องต้นเกี่ยวกับแมชชีนเลิร์นนิงโดย Andrew Ng จาก Stanford ที่ Coursera เขาได้ให้คำตอบหนึ่งบรรทัดต่อไปนี้สำหรับปัญหางานเลี้ยงค็อกเทลเนื่องจากแหล่งที่มาของเสียงถูกบันทึกโดยไมโครโฟนสองตัวที่แยกกัน

[W,s,v]=svd((repmat(sum(x.*x,1),size(x,1),1).*x)*x');

ที่ด้านล่างของสไลด์คือ "แหล่งที่มา: Sam Roweis, Yair Weiss, Eero Simoncelli" และที่ด้านล่างของสไลด์ก่อนหน้าคือ "คลิปเสียงเอื้อเฟื้อโดย Te-Won Lee" ในวิดีโอศาสตราจารย์ Ng พูดว่า

"ดังนั้นคุณอาจมองไปที่การเรียนรู้ที่ไม่มีผู้ดูแลเช่นนี้และถามว่า 'การใช้สิ่งนี้ซับซ้อนแค่ไหน?' ดูเหมือนว่าในการสร้างแอปพลิเคชันนี้ดูเหมือนว่าจะทำการประมวลผลเสียงนี้คุณจะต้องเขียนโค้ดจำนวนมากหรืออาจเชื่อมโยงไปยังไลบรารี C ++ หรือ Java จำนวนมากที่ประมวลผลเสียงดูเหมือนว่ามันจะเป็นจริงๆ โปรแกรมที่ซับซ้อนในการทำเสียงนี้: แยกเสียงออกไปและอื่น ๆ ปรากฎว่าอัลกอริทึมทำสิ่งที่คุณเพิ่งได้ยินซึ่งสามารถทำได้โดยใช้โค้ดเพียงบรรทัดเดียว ... แสดงไว้ที่นี่นักวิจัยใช้เวลานาน เพื่อสร้างโค้ดบรรทัดนี้ดังนั้นฉันไม่ได้บอกว่านี่เป็นปัญหาที่ง่าย แต่ปรากฎว่าเมื่อคุณใช้สภาพแวดล้อมการเขียนโปรแกรมที่เหมาะสมอัลกอริทึมการเรียนรู้จำนวนมากจะเป็นโปรแกรมสั้น ๆ จริงๆ "

ผลลัพธ์เสียงแยกที่เล่นในการบรรยายวิดีโอนั้นไม่สมบูรณ์แบบ แต่ในความคิดของฉันมันยอดเยี่ยมมาก ใครมีข้อมูลเชิงลึกว่าโค้ดหนึ่งบรรทัดทำงานได้ดีเพียงใด โดยเฉพาะอย่างยิ่งมีใครทราบข้อมูลอ้างอิงที่อธิบายการทำงานของ Te-Won Lee, Sam Roweis, Yair Weiss และ Eero Simoncelli เกี่ยวกับรหัสบรรทัดเดียวหรือไม่?

อัปเดต

เพื่อแสดงให้เห็นถึงความไวของอัลกอริทึมต่อระยะการแยกไมโครโฟนการจำลองต่อไปนี้ (ใน Octave) จะแยกโทนเสียงออกจากเครื่องกำเนิดโทนเสียงที่แยกจากกันสองตัว

% define model 
f1 = 1100;              % frequency of tone generator 1; unit: Hz 
f2 = 2900;              % frequency of tone generator 2; unit: Hz 
Ts = 1/(40*max(f1,f2)); % sampling period; unit: s 
dMic = 1;               % distance between microphones centered about origin; unit: m 
dSrc = 10;              % distance between tone generators centered about origin; unit: m 
c = 340.29;             % speed of sound; unit: m / s 

% generate tones
figure(1);
t = [0:Ts:0.025];
tone1 = sin(2*pi*f1*t);
tone2 = sin(2*pi*f2*t);
plot(t,tone1); 
hold on;
plot(t,tone2,'r'); xlabel('time'); ylabel('amplitude'); axis([0 0.005 -1 1]); legend('tone 1', 'tone 2');
hold off;

% mix tones at microphones
% assume inverse square attenuation of sound intensity (i.e., inverse linear attenuation of sound amplitude)
figure(2);
dNear = (dSrc - dMic)/2;
dFar = (dSrc + dMic)/2;
mic1 = 1/dNear*sin(2*pi*f1*(t-dNear/c)) + \
       1/dFar*sin(2*pi*f2*(t-dFar/c));
mic2 = 1/dNear*sin(2*pi*f2*(t-dNear/c)) + \
       1/dFar*sin(2*pi*f1*(t-dFar/c));
plot(t,mic1);
hold on;
plot(t,mic2,'r'); xlabel('time'); ylabel('amplitude'); axis([0 0.005 -1 1]); legend('mic 1', 'mic 2');
hold off;

% use svd to isolate sound sources
figure(3);
x = [mic1' mic2'];
[W,s,v]=svd((repmat(sum(x.*x,1),size(x,1),1).*x)*x');
plot(t,v(:,1));
hold on;
maxAmp = max(v(:,1));
plot(t,v(:,2),'r'); xlabel('time'); ylabel('amplitude'); axis([0 0.005 -maxAmp maxAmp]); legend('isolated tone 1', 'isolated tone 2');
hold off;

หลังจากใช้งานบนคอมพิวเตอร์แล็ปท็อปของฉันประมาณ 10 นาทีการจำลองจะสร้างตัวเลขสามตัวต่อไปนี้ซึ่งแสดงให้เห็นว่าโทนเสียงที่แยกได้ทั้งสองมีความถี่ที่ถูกต้อง

รูปที่ 1 รูปที่ 2 รูปที่ 3

อย่างไรก็ตามการตั้งค่าระยะห่างการแยกไมโครโฟนเป็นศูนย์ (เช่น dMic = 0) ทำให้การจำลองสร้างตัวเลขสามตัวต่อไปนี้ที่แสดงการจำลองไม่สามารถแยกโทนเสียงที่สองได้ (ยืนยันโดยคำในแนวทแยงที่มีนัยสำคัญเพียงคำเดียวที่ส่งคืนในเมทริกซ์ของ svd)

รูปที่ 1 โดยไม่มีการแยกไมค์ รูปที่ 2 โดยไม่มีการแยกไมค์ รูปที่ 3 โดยไม่มีการแยกไมค์

ฉันหวังว่าระยะห่างการแยกไมโครโฟนบนสมาร์ทโฟนจะใหญ่พอที่จะให้ผลลัพธ์ที่ดี แต่การตั้งค่าระยะการแยกไมโครโฟนเป็น 5.25 นิ้ว (เช่น dMic = 0.1333 เมตร) ทำให้การจำลองสร้างสิ่งต่อไปนี้น้อยกว่าการให้กำลังใจตัวเลขที่แสดงให้เห็นสูงขึ้น ส่วนประกอบความถี่ในโทนเสียงแรกที่แยกได้

รูปที่ 1 บนสมาร์ทโฟน รูปที่ 2 บนสมาร์ทโฟน รูปที่ 3 บนสมาร์ทโฟน


1
ฉันมีความทรงจำที่คลุมเครือเกี่ยวกับการบรรยายนี้ แต่จำไม่ได้ว่าxคืออะไร มันคือสเปกโตรแกรมของรูปคลื่นหรืออะไร?
Isaac

ศาสตราจารย์อึ้งที่ t = 5:30 ในวิดีโอแนะนำ 4 เรื่องการเรียนรู้ที่ไม่มีผู้ดูแลดูเหมือนจะแนะนำว่า x เป็นเวกเตอร์ของตัวอย่างเสียง บางทีส่วน repmat ในอาร์กิวเมนต์ svd กำลังใช้การปรับมาตรฐานกำลังของสัญญาณบางประเภท
gregS

คำตอบ:


30

ฉันพยายามคิดออกเช่นกัน 2 ปีต่อมา แต่ฉันได้รับคำตอบ หวังว่ามันจะช่วยใครสักคนได้

คุณต้องมีการบันทึกเสียง 2 รายการ คุณจะได้รับตัวอย่างเสียงจากhttp://research.ics.aalto.fi/ica/cocktail/cocktail_en.cgi

ข้อมูลอ้างอิงสำหรับการนำไปใช้คือhttp://www.cs.nyu.edu/~roweis/kica.html

ตกลงนี่คือรหัส -

[x1, Fs1] = audioread('mix1.wav');
[x2, Fs2] = audioread('mix2.wav');
xx = [x1, x2]';
yy = sqrtm(inv(cov(xx')))*(xx-repmat(mean(xx,2),1,size(xx,2)));
[W,s,v] = svd((repmat(sum(yy.*yy,1),size(yy,1),1).*yy)*yy');

a = W*xx; %W is unmixing matrix
subplot(2,2,1); plot(x1); title('mixed audio - mic 1');
subplot(2,2,2); plot(x2); title('mixed audio - mic 2');
subplot(2,2,3); plot(a(1,:), 'g'); title('unmixed wave 1');
subplot(2,2,4); plot(a(2,:),'r'); title('unmixed wave 2');

audiowrite('unmixed1.wav', a(1,:), Fs1);
audiowrite('unmixed2.wav', a(2,:), Fs1);

ใส่คำอธิบายภาพที่นี่


1
คุณสามารถค้นหาข้อมูลอ้างอิงที่อธิบายเหตุผลที่ชัดเจนยิ่งขึ้นสำหรับบรรทัดของโค้ดนั้นได้หรือไม่?
Hans

คุณช่วยอธิบายวิธีการผสมสัญญาณในลิงค์ที่คุณให้มาได้ไหม การใช้รหัสของคุณเป็นการดีที่จะแยกแหล่งเสียงสองแหล่งจากไฟล์ผสมสองไฟล์ที่ดาวน์โหลดจากไซต์ อย่างไรก็ตามเมื่อฉันพยายามผสมสัญญาณสองสัญญาณเข้าด้วยกันดูเหมือนว่าอัลกอริทึมจะไม่สามารถให้ผลลัพธ์ที่ถูกต้องได้ ฉันใช้วิธีไร้เดียงสาในการรับสัญญาณผสม: mic1 = 0.3 * track1 + 0.5 * track2, mic2 = 0.5 * track1 + 0.3 * track2 นี่คือสัญญาณที่ฉันพยายามป้อนให้กับอัลกอริทึม ขอบคุณมาก!
yc2986

ฉันยังใหม่กับ Matlab ฉันมีข้อผิดพลาดในบรรทัดที่ 3 บอกว่ามีปัญหาในการเชื่อมเมทริกซ์ 2 มิติที่ต่างกัน ฉันควรจัดการกับปัญหานี้อย่างไร?
mshrestha

1
ฉันลองใช้รหัสนั้นแล้ว แต่มันใช้งานได้ไม่ดีนัก ... (ไม่โทษคุณ !!)
ander understand

17

x(t) เป็นเสียงต้นฉบับจากช่อง / ไมโครโฟนหนึ่งช่อง

X = repmat(sum(x.*x,1),size(x,1),1).*x)*x'เป็นการประมาณสเปกตรัมกำลังของx(t). แม้ว่าX' = Xช่วงเวลาระหว่างแถวและคอลัมน์จะไม่เท่ากันเลย แต่ละแถวแสดงเวลาของสัญญาณในขณะที่แต่ละคอลัมน์เป็นความถี่ ผมคิดว่านี่คือการประมาณค่าและความเรียบง่ายของการแสดงออกที่เรียกว่าที่เข้มงวดมากขึ้นspectrogram

Singular Value Decompositionบนสเปกโตรแกรมใช้เพื่อแยกสัญญาณออกเป็นส่วนประกอบต่างๆตามข้อมูลสเปกตรัม ค่าในแนวทแยงsคือขนาดของส่วนประกอบสเปกตรัมที่แตกต่างกัน แถวในuและคอลัมน์ในv'เป็นเวกเตอร์มุมฉากที่จับคู่องค์ประกอบความถี่ด้วยขนาดที่สอดคล้องกันกับXช่องว่าง

ฉันไม่มีข้อมูลเสียงที่จะทดสอบ แต่ในความเข้าใจของฉันโดย SVD ส่วนประกอบที่ตกอยู่ในเวกเตอร์มุมฉากที่คล้ายกันหวังว่าจะรวมกลุ่มกันได้ด้วยความช่วยเหลือของการเรียนรู้ที่ไม่มีผู้ดูแล สมมติว่าหากมีการรวมกลุ่มขนาดเส้นทแยงมุม 2 ตัวแรกจาก s ก็u*s_new*v'จะสร้างเสียงคนเดียวโดยที่s_newเหมือนกันsยกเว้นองค์ประกอบทั้งหมดที่(3:end,3:end)จะถูกกำจัดออกไป

สองบทความเกี่ยวกับเมทริกซ์ที่เกิดเสียงและSVDมีไว้สำหรับการอ้างอิงของคุณ


1
gregS ในทางคณิตศาสตร์เมทริกซ์ n-by-2 x ยังคงสามารถสร้าง X ได้ด้วยการดำเนินการ repmat อย่างไรก็ตามโปรแกรมสเปกตรัมสามารถแสดงช่องได้ในแต่ละครั้งเท่านั้น ดังนั้นฉันคิดว่ามันสมเหตุสมผลกว่าที่จะใช้ n-by-1 x ในแต่ละครั้งและถือว่าปัญหาเป็นการถดถอยเชิงเส้น (สมการเมทริกซ์สองตัว) อีกสองแนวทางที่เป็นไปได้คือ (i) เฉลี่ยสองช่องเป็น n-by-2 x; หรือ (ii) ผูกเข้าด้วยกันเพื่อสร้าง 2 * n-by-2 x
lennon310

2
gregS ฉันพิจารณาคำถามของคุณอีกครั้ง อาจใช้งานได้ถ้าคุณใช้ repmat บน n-by-2 x ในทางกายภาพสามารถมองได้ว่าเป็นค่าเฉลี่ยของกำลังไฟฟ้าจากสองช่องสัญญาณในแต่ละครั้งและแต่ละความถี่
lennon310

ฉันพบโพสต์นี้หลังจากดูวิดีโอแนะนำ Machine Learning (หลักสูตรนี้เพิ่งเริ่มขึ้นอีกครั้ง) ฉันสงสัยว่าคุณสามารถสร้างการแยกเสียงที่แสดงในวิดีโอได้หรือไม่หรือได้รับการพัฒนาในระหว่างการเรียนการสอน
siritinga

@siritinga โปรดค้นหาสิ่งพิมพ์ของ Andrew Ng เกี่ยวกับการเรียนรู้แบบไม่ได้รับการดูแล / การเรียนรู้เชิงลึกเกี่ยวกับเสียงขอบคุณ
lennon310

1
เหตุใด $ X $ จึงเป็นพลังของสเปกตรัมของ $ x $ ตามคำตอบของ Jack Z $ x $ ไม่ใช่เสียงต้นฉบับจากการบันทึก แต่เป็นการประมวลผลซึ่งกันและกันของค่าลักษณะเฉพาะของความแปรปรวนร่วมของเสียงต้นฉบับ
Hans
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.