จะทำการตรวจสอบความถูกต้องข้ามสำหรับ PCA เพื่อกำหนดจำนวนขององค์ประกอบหลักได้อย่างไร


12

ฉันกำลังพยายามเขียนฟังก์ชั่นของตัวเองสำหรับการวิเคราะห์องค์ประกอบหลัก PCA (แน่นอนมีหลายอย่างที่เขียนไปแล้ว แต่ฉันแค่สนใจที่จะใช้สิ่งต่าง ๆ ด้วยตัวเอง) ปัญหาหลักที่ฉันพบคือขั้นตอนการตรวจสอบข้ามและการคำนวณผลรวมของสี่เหลี่ยมที่คาดการณ์ไว้ (PRESS) มันไม่สำคัญว่าฉันจะใช้การตรวจสอบข้ามซึ่งเป็นคำถามส่วนใหญ่เกี่ยวกับทฤษฎีที่อยู่เบื้องหลัง แต่พิจารณาการตรวจสอบความถูกต้องแบบข้ามครั้งเดียว (LOOCV) จากทฤษฎีฉันพบว่าในการดำเนินการ LOOCV คุณต้อง:

  1. ลบวัตถุ
  2. ขนาดที่เหลือ
  3. ดำเนินการ PCA ด้วยองค์ประกอบจำนวนหนึ่ง
  4. ปรับขนาดวัตถุที่ถูกลบตามพารามิเตอร์ที่ได้รับใน (2)
  5. ทำนายวัตถุตามโมเดล PCA
  6. คำนวณ PRESS สำหรับวัตถุนี้
  7. ปฏิบัติขั้นตอนวิธีเดียวกันกับวัตถุอื่นอีกครั้ง
  8. สรุปค่า PRESS ทั้งหมด
  9. กำไร

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

คุณช่วยบอกฉันหน่อยได้ไหมว่าสิ่งที่ฉันใช้ในขั้นตอนการตรวจสอบข้ามถูกต้องหรือไม่:

case 'loocv'

% # n - number of objects
% # p - number of variables
% # vComponents - the number of components used in CV
dataSets = divideData(n,n); 
         % # it is just a variable responsible for creating datasets for CV 
         % #  (for LOOCV datasets will be equal to [1, 2, 3, ... , n]);'
tempPRESS = zeros(n,vComponents);

for j = 1:n
  Xmodel1 = X; % # X - n x p original matrix
  Xmodel1(dataSets{j},:) = []; % # delete the object to be predicted
  [Xmodel1,Xmodel1shift,Xmodel1div] = skScale(Xmodel1, 'Center', vCenter, 
                                              'Scaling', vScaling); 
          % # scale the data and extract the shift and scaling factor
  Xmodel2 = X(dataSets{j},:); % # the object to be predicted
  Xmodel2 = bsxfun(@minus,Xmodel2,Xmodel1shift); % # shift and scale the object
  Xmodel2 = bsxfun(@rdivide,Xmodel2,Xmodel1div);
  [Xscores2,Xloadings2] = myNipals(Xmodel1,0.00000001,vComponents); 
          % # the way to calculate the scores and loadings
                % # Xscores2 - n x vComponents matrix
                % # Xloadings2 - vComponents x p matrix
  for i = 1:vComponents
    tempPRESS(j,i) = sum(sum((Xmodel2* ...
       (eye(p) - transpose(Xloadings2(1:i,:))*Xloadings2(1:i,:))).^2));
  end
end
PRESS = sum(tempPRESS,1);

ในซอฟต์แวร์ ( PLS_Toolbox ) มันทำงานได้ดังนี้:

for i = 1:vComponents
    tempPCA = eye(p) - transpose(Xloadings2(1:i,:))*Xloadings2(1:i,:);
    for kk = 1:p
        tempRepmat(:,kk) = -(1/tempPCA(kk,kk))*tempPCA(:,kk);
          % # this I do not understand
        tempRepmat(kk,kk) = -1; 
          % # here is some normalization that I do not get
    end 
    tempPRESS(j,i) = sum(sum((Xmodel2*tempRepmat).^2)); 
end

ดังนั้นพวกเขาจึงทำการฟื้นฟูโดยใช้tempRepmatตัวแปรนี้: เหตุผลเดียวที่ฉันพบคือพวกเขาใช้ LOOCV สำหรับ PCA ที่แข็งแกร่ง น่าเสียดายที่ทีมสนับสนุนไม่ต้องการตอบคำถามของฉันเนื่องจากฉันมีเพียงเวอร์ชั่นเดโมของซอฟต์แวร์


ตรวจสอบเพิ่มเติมหากฉันเข้าใจตัวอย่างข้อมูลการฟื้นฟูเพิ่มเติม: บทบาทของtempRepmat(kk,kk) = -1บรรทัดคืออะไร บรรทัดก่อนหน้านี้ไม่แน่ใจแล้วหรือว่าtempRepmat(kk,kk)เท่ากับ -1 หรือไม่ นอกจากนี้ทำไม minuses? ข้อผิดพลาดกำลังจะถูกยกกำลังสองอยู่แล้วดังนั้นฉันจะเข้าใจอย่างถูกต้องว่าถ้าเอา minuses ออกจะไม่มีอะไรเปลี่ยนแปลง?
อะมีบา

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

ฉันกำลังมองหารหัส R เทียบเท่ากับรหัส MATLAB ที่ให้ไว้ในคำตอบและได้รับรางวัล
AIM_BLB

3
@CSA การขอรหัสปิดหัวข้อได้ที่นี่ (แม้น่าจะเป็นผ่านความคิดเห็น & รางวัล) คุณควรจะสามารถถามได้ในStack Overflow : คุณสามารถคัดลอกโค้ดอ้างอิงแหล่งที่มาพร้อมลิงค์ที่นี่และขอคำแปล ฉันเชื่อว่าทุกอย่างจะอยู่ในหัวข้อนั้น
gung - Reinstate Monica

คำตอบ:


21

สิ่งที่คุณทำผิด: มันไม่สมเหตุสมผลเลยที่จะคำนวณ PRESS สำหรับ PCA อย่างนั้น! ปัญหาอยู่ในขั้นตอนที่ # 5 ของคุณ


วิธีการไร้เดียงสาเพื่อกดสำหรับ PCA

ให้ชุดข้อมูลประกอบด้วยคะแนนในพื้นที่มิติ:n ในการคำนวณข้อผิดพลาดในการสร้างใหม่สำหรับจุดข้อมูลการทดสอบเดียวคุณดำเนินการ PCA ในชุดการฝึกอบรมโดยที่ไม่รวมประเด็นนี้ให้ใช้จำนวนของแกนหลัก เป็นคอลัมน์ของและพบข้อผิดพลาดในการสร้างใหม่เป็น 2 กดเท่ากับผลรวมของตัวอย่างทดสอบทั้งหมดd x ( i )R d ,ndx(i)Rd,i=1nx(i)X(i)kU(i)x(i)x^(i)2=x(i)U(i)[U(i)]x(i)2iดังนั้นสมการที่สมเหตุสมผลน่าจะเป็น:

PRESS=?i=1nx(i)U(i)[U(i)]x(i)2.

เพื่อความเรียบง่ายฉันไม่สนใจปัญหาของการตั้งศูนย์และปรับขนาดที่นี่

วิธีการไร้เดียงสาผิด

ปัญหาข้างต้นคือเราใช้เพื่อคำนวณการคาดการณ์และนั่นเป็นสิ่งที่แย่มากx(i)x^(i)

สังเกตเห็นความแตกต่างที่สำคัญกับกรณีการถดถอยที่สูตรการสร้างข้อผิดพลาดโดยพื้นฐานแล้วคือแต่การทำนาย จะคำนวณโดยใช้ตัวแปรและไม่ใช้{(i)} สิ่งนี้เป็นไปไม่ได้ใน PCA เนื่องจากใน PCA ไม่มีตัวแปรตามและอิสระ: ตัวแปรทั้งหมดได้รับการปฏิบัติด้วยกันy(i)y^(i)2y^(i)y(i)

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

แนวทางที่ถูกต้อง

มีหลายวิธีที่เป็นไปได้ดูBro et al (2008) การตรวจสอบความถูกต้องของโมเดลส่วนประกอบ: การตรวจสอบวิธีการที่สำคัญในปัจจุบันสำหรับภาพรวมและการเปรียบเทียบ วิธีหนึ่งคือออกจากมิติข้อมูลหนึ่งจุดในแต่ละครั้ง (เช่นแทน ) เพื่อให้ข้อมูลการฝึกอบรมกลายเป็นเมทริกซ์ที่มีค่าขาดหายไปหนึ่งค่า และจากนั้นเพื่อทำนาย ("impute") ค่าที่หายไปนี้ด้วย PCA (แน่นอนหนึ่งสามารถสุ่มถือส่วนเมทริกซ์ที่มีขนาดใหญ่กว่าเช่น 10%) ปัญหาคือการคำนวณ PCA ที่มีค่าที่หายไปนั้นสามารถคำนวณได้ค่อนข้างช้า (ขึ้นอยู่กับอัลกอริธึม EM) แต่ต้องทำซ้ำหลาย ๆ ครั้งที่นี่ อัปเดต: ดูhttp://alexhwilliams.info/itsneuronalblog/2018/02/26/crossval/xj(i)x(i) สำหรับการสนทนาที่ดีและการใช้งาน Python (PCA ที่มีค่าที่ขาดหายไปจะถูกนำไปใช้ผ่านการสลับกำลังสองน้อยที่สุด)

วิธีการที่ฉันพบว่าใช้งานได้จริงมากขึ้นคือการทิ้งจุดข้อมูลหนึ่งจุดในแต่ละครั้งให้คำนวณ PCA ในข้อมูลการฝึกอบรม (ตรงกับด้านบน) แต่จากนั้นวนรอบมิติของปล่อยพวกมันทีละตัวและคำนวณข้อผิดพลาดในการสร้างใหม่โดยใช้ส่วนที่เหลือ สิ่งนี้อาจสร้างความสับสนในการเริ่มต้นและสูตรมีแนวโน้มที่จะยุ่งเหยิง แต่การนำไปปฏิบัติค่อนข้างตรงไปตรงมา ก่อนอื่นให้ฉันทำสูตร (ค่อนข้างน่ากลัว) แล้วอธิบายสั้น ๆ :x(i)x(i)

PRESSPCA=i=1nj=1d|xj(i)[U(i)[Uj(i)]+xj(i)]j|2.

ลองพิจารณาวงในที่นี่ เราออกจากจุดหนึ่งและคำนวณองค์ประกอบหลักเกี่ยวกับข้อมูลการฝึกอบรมi)} ตอนนี้เรารักษาแต่ละค่าเป็นแบบทดสอบและใช้ส่วนที่เหลือเพื่อทำการคาดการณ์ . การทำนายเป็นพิกัด -th ของ "การฉายภาพ" (ในความหมายกำลังสองน้อยที่สุด) ของลงบนสเปซ โดยi)} ในการคำนวณหาจุดในพื้นที่ PCที่ใกล้เคียงที่สุดx(i)kU(i)xj(i)xj(i)Rd1x^j(i)jxj(i)U(i)z^Rkxj(i)โดยการคำนวณโดยที่คือพร้อมแถว -th เตะออกแล้วและย่อมาจาก pseudoinverse ตอนนี้แผนที่กลับสู่พื้นที่เดิม:และใช้เวลาของ -th ประสานงาน[\ z^=[Uj(i)]+xj(i)RkUj(i)U(i)j[]+z^U(i)[Uj(i)]+xj(i)j[]j

การประมาณค่ากับวิธีการที่ถูกต้อง

ฉันไม่เข้าใจการปรับมาตรฐานเพิ่มเติมที่ใช้ใน PLS_Toolbox แต่นี่เป็นวิธีหนึ่งที่ไปในทิศทางเดียวกัน

มีวิธีอื่นในการแมปบนพื้นที่ของส่วนประกอบหลัก:นั่นคือเพียงแค่เปลี่ยนทรานแซกชันแทนหลอก - ผกผัน กล่าวอีกนัยหนึ่งมิติที่เหลือไว้สำหรับการทดสอบจะไม่ถูกนับรวมและน้ำหนักที่สอดคล้องกันก็จะถูกเตะออกไป ฉันคิดว่าสิ่งนี้ควรมีความแม่นยำน้อยกว่า แต่บ่อยครั้งอาจยอมรับได้ สิ่งที่ดีคือตอนนี้สูตรผลลัพธ์สามารถเป็น vectorized ได้ดังนี้ (ฉันไม่ได้คำนวณ):xj(i)z^approx=[Uj(i)]xj(i)

PRESSPCA,approx=i=1nj=1d|xj(i)[U(i)[Uj(i)]xj(i)]j|2=i=1n(IUU+diag{UU})x(i)2,

โดยที่ฉันเขียนเป็นเพื่อความกะทัดรัดและหมายถึงการตั้งค่าองค์ประกอบที่ไม่ใช่แนวทแยงทั้งหมดให้เป็นศูนย์ โปรดทราบว่าสูตรนี้ดูเหมือนว่าสูตรแรก (ซื่อๆไร้เดียงสา) ที่มีการแก้ไขเล็กน้อย! โปรดทราบว่าการแก้ไขนี้ขึ้นอยู่กับแนวทแยงมุมของเช่นเดียวกับในรหัส PLS_Toolbox อย่างไรก็ตามสูตรนี้ยังคงแตกต่างจากที่ใช้ใน PLS_Toolbox และความแตกต่างนี้ฉันไม่สามารถอธิบายได้U(i)Udiag{}UU

Update (ก.พ. 2018):ด้านบนฉันเรียกขั้นตอนหนึ่งว่า "ถูกต้อง" และอีก "โดยประมาณ" แต่ฉันไม่แน่ใจอีกต่อไปว่านี่จะมีความหมาย ทั้งสองขั้นตอนมีเหตุผลและฉันคิดว่าไม่ถูกต้องมากขึ้น ฉันชอบที่ขั้นตอน "โดยประมาณ" มีสูตรที่ง่ายกว่า นอกจากนี้ฉันยังจำได้ว่าฉันมีชุดข้อมูลบางส่วนที่ขั้นตอน "โดยประมาณ" ให้ผลลัพธ์ที่ดูมีความหมายมากขึ้น น่าเสียดายที่ฉันจำรายละเอียดไม่ได้อีกแล้ว


ตัวอย่าง

นี่คือวิธีการเปรียบเทียบวิธีเหล่านี้สำหรับสองชุดข้อมูลที่รู้จักกันดี: ชุดข้อมูล Iris และชุดข้อมูลไวน์ โปรดทราบว่าวิธีการที่ไร้เดียงสาจะสร้างเส้นโค้งที่ลดลงแบบ monotonically ในขณะที่อีกสองวิธีให้ผลลัพธ์เป็นเส้นโค้งที่มีค่าต่ำสุด โปรดทราบว่าในกรณีของไอริสวิธีการประมาณแนะนำพีซี 1 เครื่องเป็นหมายเลขที่เหมาะสมที่สุด แต่วิธีการ pseudoinverse แนะนำพีซี 2 เครื่อง (และเมื่อมองไปที่ชุด PCA ใด ๆ สำหรับชุดข้อมูล Iris ดูเหมือนว่าทั้งพีซีเครื่องแรกจะมีสัญญาณบ้าง) และในกรณีไวน์วิธีการ pseudoinverse นั้นชี้ให้เห็นอย่างชัดเจนในพีซี 3 เครื่องในขณะที่วิธีการประมาณไม่สามารถตัดสินใจได้ระหว่าง 3 และ 5

ป้อนคำอธิบายรูปภาพที่นี่


รหัส Matlab เพื่อดำเนินการตรวจสอบข้ามและพล็อตผลลัพธ์

function pca_loocv(X)

%// loop over data points 
for n=1:size(X,1)
    Xtrain = X([1:n-1 n+1:end],:);
    mu = mean(Xtrain);
    Xtrain = bsxfun(@minus, Xtrain, mu);
    [~,~,V] = svd(Xtrain, 'econ');
    Xtest = X(n,:);
    Xtest = bsxfun(@minus, Xtest, mu);

    %// loop over the number of PCs
    for j=1:min(size(V,2),25)
        P = V(:,1:j)*V(:,1:j)';        %//'
        err1 = Xtest * (eye(size(P)) - P);
        err2 = Xtest * (eye(size(P)) - P + diag(diag(P)));
        for k=1:size(Xtest,2)
            proj = Xtest(:,[1:k-1 k+1:end])*pinv(V([1:k-1 k+1:end],1:j))'*V(:,1:j)'; 
            err3(k) = Xtest(k) - proj(k);
        end

        error1(n,j) = sum(err1(:).^2);
        error2(n,j) = sum(err2(:).^2);
        error3(n,j) = sum(err3(:).^2);
    end    
end

error1 = sum(error1);
error2 = sum(error2);
error3 = sum(error3);
%// plotting code
figure
hold on
plot(error1, 'k.--')
plot(error2, 'r.-')
plot(error3, 'b.-')
legend({'Naive method', 'Approximate method', 'Pseudoinverse method'}, ...
    'Location', 'NorthWest')
legend boxoff
set(gca, 'XTick', 1:length(error1))
set(gca, 'YTick', [])
xlabel('Number of PCs')
ylabel('Cross-validation error')

ขอบคุณสำหรับคำตอบ! ฉันรู้ว่ากระดาษ และฉันใช้การตรวจสอบข้ามแถวแบบชาญฉลาดซึ่งอธิบายไว้ที่นั่น (ดูเหมือนว่าจะตรงกับรหัสที่ฉันให้ไว้) ฉันเปรียบเทียบกับซอฟต์แวร์ PLS_Toolbox แต่มีโค้ดหนึ่งบรรทัดใน LOOCV ที่ฉันไม่เข้าใจจริงๆ (ฉันเขียนไว้ในคำถามเดิม)
คิริลล์

ใช่พวกเขาเรียกมันว่า "การตรวจสอบข้ามแถวแบบฉลาด" และการใช้งานของคุณดูเหมือนดี แต่โปรดทราบว่านี่เป็นวิธีที่ไม่ดีในการดำเนินการตรวจสอบข้าม (ตามที่ระบุไว้และแสดงให้เห็นโดยประจักษ์ใน Bro et al.) อย่าใช้มัน! เกี่ยวกับบรรทัดรหัสที่คุณไม่เข้าใจคุณจะอัปเดตคำถามของคุณหรือไม่ ไม่แน่ใจว่าคุณหมายถึงอะไร
อะมีบา

สิ่งสำคัญคือการใช้งานนี้ดูเหมือนจะมีความสามารถในการเข้าถึงขั้นต่ำใน CV
คิริลล์

PRESS ofใกล้เคียงกับ LOO% อธิบายความแปรปรวน - ฉันจะไม่พูดว่าสิ่งนี้ดีหรือไม่ดี แต่มันเป็นสิ่งที่เราต้องระวัง และเช่นเดียวกับการอธิบายความแปรปรวนจะเข้าใกล้ 1 เนื่องจากโมเดล PCA เข้าใกล้อันดับของชุดข้อมูล X PRESS นี้จะเข้าใกล้ 0x^x
cbeleites ไม่มีความสุขกับ SX

@ Kirill: ขอขอบคุณข้อมูลโค้ดที่เข้าท่าตอนนี้ (บางทีคุณสามารถลบความคิดเห็นข้างต้นที่ล้าสมัยไปแล้ว) ฉันไม่รู้ว่ามันควรทำอะไร แต่ถ้าคุณบอกว่ามันทำให้เกิดข้อผิดพลาดในการคาดคะเนถึงขั้นต่ำมันก็น่าจะมีบทลงโทษสำหรับมีขนาดใหญ่ขึ้น(จำนวนขององค์ประกอบ; เช่นตัวแปรในรหัสของคุณ) สุจริตฉันจะสงสัยในวิธีการดังกล่าวใด ๆ (เว้นแต่จะมีเหตุผลทางทฤษฎีที่จะ) โดยเฉพาะอย่างยิ่งเนื่องจากมีวิธีการที่ดีขึ้นตามที่ฉันอธิบายไว้ในคำตอบของฉัน ki
อะมีบา

1

หากต้องการเพิ่มจุดทั่วไปให้กับคำตอบที่ดีของ @ amoeba:

ความแตกต่างที่เป็นประโยชน์และสำคัญอย่างหนึ่งระหว่างโมเดลที่อยู่ภายใต้การดูแลและไม่ได้รับการดูแลคือสำหรับโมเดลที่ไม่ได้รับการสำรองคุณจำเป็นต้องคิดให้หนักกว่าสิ่งที่คุณเห็นว่าเทียบเท่าและไม่ได้

แบบจำลองภายใต้การดูแลมักมีเอาต์พุตสุดท้ายในแบบที่คุณไม่จำเป็นต้องสนใจมากนัก: โดยคำจำกัดความและโครงสร้างอ้างว่ามีความหมายเหมือนกับดังนั้นคุณจึงสามารถเปรียบเทียบได้โดยตรงy^y^y

ในการสร้างการวัดประสิทธิภาพที่มีความหมายคุณต้องคิดว่าอิสระในรูปแบบใดมีความหมายสำหรับแอปพลิเคชันของคุณ นั่นจะนำไปสู่การกดบนคะแนนซึ่งอาจเป็น (ปกติ?) หลังจากการหมุน / พลิกเหมือน Procrustes

กด xฉันเดา (ตอนนี้ฉันไม่มีเวลารู้ว่าโค้ด 2 บรรทัดของพวกเขาทำอะไร - แต่บางทีคุณอาจก้าวผ่านบรรทัดและดูได้):

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


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

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