Putar komponen PCA untuk menyamakan varians di setiap komponen

9

Saya mencoba mengurangi dimensi dan derau dataset dengan melakukan PCA pada dataset dan membuang beberapa PC terakhir. Setelah itu, saya ingin menggunakan beberapa algoritma pembelajaran mesin pada PC yang tersisa, dan karena itu saya ingin menormalkan data dengan menyamakan varians PC untuk membuat algoritma bekerja lebih baik.

Satu cara sederhana adalah dengan hanya menormalkan varians ke nilai unit. Namun, PC pertama berisi lebih banyak varians dari dataset asli daripada yang berikut, dan saya masih ingin memberikan lebih banyak "bobot". Karena itu saya bertanya-tanya: adakah cara sederhana untuk hanya memisahkan variansnya dan membaginya dengan PC dengan varian yang lebih sedikit?

Cara lain adalah memetakan PC kembali ke ruang fitur asli, tetapi dalam hal itu dimensi juga akan meningkat ke nilai aslinya.

Saya kira lebih baik untuk menjaga kolom yang dihasilkan ortogonal, tetapi itu tidak perlu saat ini.

feilong
sumber
1
Tidak ... varimax memaksimalkan jumlah dari varian kuadrat dari pemuatan, sehingga mencoba membuatnya tidak sama mungkin. Juga, mengapa Anda ingin menyamakan komponen? Intinya adalah untuk menangkap variasi sebanyak mungkin dalam komponen sesedikit mungkin.
2
Apakah sekadar menstandarkan skor komponen ke varian unit tidak cocok untuk Anda? Kenapa begitu? Apa jenis hasil yang Anda inginkan - haruskah kolom yang dihasilkan tidak berkorelasi di samping varian yang sama?
ttnphns
2
Dari uraian Anda, sepertinya Anda hanya ingin "memutar" data (dimensi yang diperkecil). Ini sering dilakukan sebagai langkah preprocessing dalam pembelajaran mesin. Untuk mencapainya, Anda cukup melakukan PCA, memilih beberapa komponen, dan membakukannya. Saya kira dimungkinkan untuk menemukan rotasi ortogonal (seperti varimax) yang merotasi komponen terstandarisasi sehingga mereka tetap tidak berkorelasi tetapi menjelaskan jumlah varians yang persis sama; itu pertanyaan yang menarik, saya harus memikirkannya. Tapi saya belum pernah melihat ini dilakukan, pasti tidak dalam pembelajaran mesin.
amoeba
2
Ngomong-ngomong, apa "beberapa algoritma pembelajaran mesin" yang ingin Anda terapkan setelah PCA? Ini mungkin relevan.
amoeba
1
Perhatikan bahwa jika Anda memutar PC standar Anda, maka jaraknya tidak akan berubah sama sekali! Jadi itu benar-benar tidak masalah untuk algoritma berbasis jarak berikutnya.
amoeba

Jawaban:

10

Tidak sepenuhnya jelas bagi saya bahwa apa yang Anda tanyakan adalah apa yang benar-benar Anda butuhkan: langkah preprocessing yang umum dalam pembelajaran mesin adalah pengurangan dimensi + pemutihan, yang berarti melakukan PCA dan menstandarisasi komponen, tidak ada yang lain. Tetapi saya akan tetap fokus pada pertanyaan Anda seperti yang dirumuskan, karena itu lebih menarik.


Biarkan menjadi pusat data matriks dengan titik data dalam baris dan variabel dalam kolom. PCA sama dengan dekomposisi nilai singular mana untuk melakukan pengurangan dimensionalitas kita hanya menyimpan komponen . "Rotasi faktor" ortogonal dari komponen-komponen ini menyiratkan memilih ortogonal matrix dan menghubungkannya ke dalam dekomposisi: n × d X = U S VU k S k V kXn×dk k × k R XU k S k V k = U k R RS k V k =

X=USVUkSkVk,
kk×kR
XUkSkVk=UkRRSkVk=n1UkRRotatedstandardized scoresRSkVk/n1Rotated loadings.
Di sini adalah komponen yang diputar standar dan istilah kedua mewakili pemuatan yang diputar ditransformasikan. Varians setiap komponen setelah rotasi diberikan oleh jumlah kuadrat dari vektor pemuatan yang sesuai; sebelum rotasi, cukup . Setelah rotasi itu adalah hal lain.s 2 i /(n-1)n1UkRsi2/(n1)

Sekarang kita siap untuk merumuskan masalah dalam istilah matematika: diberikan pembebanan yang tidak diputar , cari matriks rotasi sedemikian rupa sehingga pembebanan yang diputar, , memiliki jumlah kuadrat yang sama di setiap kolom. RLRL=VkSk/n1RLR

Mari kita selesaikan. Jumlah kolom kuadrat setelah rotasi sama dengan elemen diagonal Ini masuk akal: rotasi hanya mendistribusikan ulang varian komponen, yang awalnya diberikan oleh , di antara mereka, sesuai dengan rumus ini. Kita perlu mendistribusikannya kembali sehingga semuanya menjadi sama dengan nilai rata-rata mereka .s 2 i /(n-1)μ

(LR)LR=RS2n1R.
si2/(n1)μ

Saya tidak berpikir ada solusi bentuk tertutup untuk ini, dan sebenarnya ada banyak solusi berbeda. Tetapi solusi dapat dengan mudah dibangun secara berurutan:

  1. Ambil komponen pertama dan komponen -th. Yang pertama memiliki varians dan yang terakhir memiliki varians .σ maks > μ σ min < μkσmax>μσmin<μ
  2. Putar hanya dua ini sehingga varians yang pertama menjadi sama dengan . Matriks rotasi dalam 2D ​​hanya bergantung pada satu parameter dan mudah untuk menuliskan persamaan dan menghitung diperlukan . Memang, dan setelah transformasi PC pertama akan mendapatkan varians dari sana kita segera memperolehθ θ R 2D = ( cos θ sin θ - sin θ cos θ ) cos 2 θμθθ
    R2D=(cosθsinθsinθcosθ)
    cos2θσmax+sin2θσmin=cos2θσmax+(1cos2θ)σmin=μ,
    cos2θ=μσminσmaxσmin.
  3. Komponen pertama sekarang selesai, ia memiliki varian .μ
  4. Lanjutkan ke pasangan berikutnya, mengambil komponen dengan varian terbesar dan satu dengan varian terkecil. Goto # 2.

Ini akan mendistribusikan ulang semua varian secara merata dengan urutan rotasi 2D. Mengalikan semua matriks rotasi ini bersama-sama akan menghasilkan keseluruhan .(k1)R


Contoh

Pertimbangkan matriks :Varians rata-rata adalah . Algoritme saya akan diproses sebagai berikut:S2/(n1)

(10000060000300001).
5
  1. Langkah 1: putar PC1 dan PC4 sehingga PC1 mendapat varian . Akibatnya, PC4 mendapat varians .51+(105)=6

  2. Langkah 2: putar PC2 (varian maksimal baru) dan PC3 sehingga PC2 mendapatkan varian . Akibatnya, PC3 mendapat varians .53+(65)=4

  3. Langkah 3: putar PC4 (varian maksimal baru) dan PC3 sehingga PC4 mendapatkan varian . Akibatnya, PC3 mendapat varians .4 + ( 6 - 1 ) = 554+(61)=5

  4. Selesai

Saya menulis skrip Matlab yang mengimplementasikan algoritma ini (lihat di bawah). Untuk matriks input ini, urutan sudut rotasi adalah:

48.1897   35.2644   45.0000

Varians komponen setelah setiap langkah (dalam baris):

10     6     3     1
 5     6     3     6
 5     5     4     6
 5     5     5     5

Matriks rotasi akhir (produk dari tiga matriks rotasi 2D):

 0.6667         0    0.5270    0.5270
      0    0.8165    0.4082   -0.4082
      0   -0.5774    0.5774   -0.5774
-0.7454         0    0.4714    0.4714

Dan matriks terakhir adalah:(LR)LR

5.0000         0    3.1623    3.1623
     0    5.0000    1.0000   -1.0000
3.1623    1.0000    5.0000    1.0000
3.1623   -1.0000    1.0000    5.0000

Ini kodenya:

S = diag([10 6 3 1]);
mu = mean(diag(S));
R = eye(size(S));

vars(1,:) = diag(S);
Supdated = S;

for i = 1:size(S,1)-1
    [~, maxV] = max(diag(Supdated));
    [~, minV] = min(diag(Supdated));

    w = (mu-Supdated(minV,minV))/(Supdated(maxV,maxV)-Supdated(minV,minV));
    cosTheta = sqrt(w);
    sinTheta = sqrt(1-w);

    R2d = eye(size(S));
    R2d([maxV minV], [maxV minV]) = [cosTheta sinTheta; -sinTheta cosTheta];
    R = R * R2d;

    Supdated = transpose(R2d) * Supdated * R2d;    

    vars(i+1,:) = diag(Supdated);
    angles(i) = acosd(cosTheta);
end

angles                %// sequence of 2d rotation angles
round(vars)           %// component variances on each step
R                     %// final rotation matrix
transpose(R)*S*R      %// final S matrix

Berikut adalah kode dalam Python yang disediakan oleh @feilong:

def amoeba_rotation(s2):
    """
    Parameters
    ----------
    s2 : array
        The diagonal of the matrix S^2.

    Returns
    -------
    R : array
        The rotation matrix R.

    Examples
    --------
    >>> amoeba_rotation(np.array([10, 6, 3, 1]))
    [[ 0.66666667  0.          0.52704628  0.52704628]
     [ 0.          0.81649658  0.40824829 -0.40824829]
     [ 0.         -0.57735027  0.57735027 -0.57735027]
     [-0.74535599  0.          0.47140452  0.47140452]]

    http://stats.stackexchange.com/a/177555/87414
    """
    n = len(s2)
    mu = s2.mean()
    R = np.eye(n)
    for i in range(n-1):
        max_v, min_v = np.argmax(s2), np.argmin(s2)
        w = (mu - s2[min_v]) / (s2[max_v] - s2[min_v])
        cos_theta, sin_theta = np.sqrt(w), np.sqrt(1-w)
        R[:, [max_v, min_v]] = np.dot(
            R[:, [max_v, min_v]],
            np.array([[cos_theta, sin_theta], [-sin_theta, cos_theta]]))
        s2[[max_v, min_v]] = [mu, s2[max_v] + s2[min_v] - mu]
    return R

Perhatikan bahwa masalah ini benar-benar setara dengan yang berikut: diberikan variabel tidak berkorelasi dengan varians , temukan rotasi (yaitu basis ortogonal baru) yang akan menghasilkan variabel dengan varians yang sama (tetapi tentu saja tidak berkorelasi lagi).σ 2 i kkσi2k

amuba
sumber
Saya kira, untuk setiap dua pasang komponen (skor mereka), sudut rotasi akan menjadi 45 derajat, untuk menyamakan varians mereka. Namun, saya tidak bisa membayangkan bagaimana melakukan seluruh tugas dengan 3+ komponen secara berpasangan.
ttnphns
1
@feilong, saya pikir menyamakan varian dari sepasang komponen pada suatu waktu adalah algoritma yang sangat suboptimal. Apa yang saya sarankan adalah memilih rotasi sedemikian sehingga varians dari satu komponen menjadi persis sama dengan varians rata-rata global. Kemudian komponen ini "selesai", dan orang dapat menangani sisanya. Ini dijamin untuk menyamakan semua varian dalam sejumlah langkah terbatas. Lihat komentar saya sebelumnya untuk contoh.
amoeba
1
@amoeba Anda benar, itu solusi yang lebih baik, dan harus diakhiri dengan langkah-langkah n-1.
feilong
1
@amoeba Saya telah menambahkan implementasi minimal saya menggunakan Python. Saya memodifikasi bagian yang mengalikan seluruh matriks, karena hal itu dapat memakan waktu untuk matriks besar.
feilong
1
@amoeba Khusus untuk komponen prinsip, dimungkinkan untuk menghemat lebih banyak waktu dengan menghapus bagian yang mencari maksimum dan minimum. Kita cukup memutar komponen ke-1 dan ke-2 (untuk membuat komponen ke-1 memiliki varian rata-rata), lalu ke-2 dan ke-3, dan seterusnya. Kami hanya perlu memastikan varians total masing-masing pasangan lebih besar dari mu.
feilong
2

XYσmax2σmin2Xμ2Yσmax2+σmin2μ2

cosθ

μ2=cos2θ(σmax2)+sin2θ(σmin2)

tetapi belum menunjukkan dari mana persamaan ini berasal; mungkin berpikir bahwa itu jelas tanpa penjelasan. Jelas atau tidak, saya percaya itu layak dijelaskan - dengan cara tertentu. Jawaban saya menyajikan satu cara.

XYθXxx

ilustrasi rotasi

x Xx=xcosθxxxxyysinθ

x=x(xx)=xcosθysinθ

μ2X

μ2=x2=(xcosθysinθ)2=(x2cos2θ+y2sin2θ2xycosθsinθ)=cos2θx2+sin2θy22cosθsinθxy=0 (X and Y are uncorrelated)=cos2θ(σmax2)+sin2θ(σmin2)

cosθ

ttnphns
sumber
2
+1. Saya tidak berpikir bahwa itu jelas (tidak), tapi saya pikir lebih mudah untuk memverifikasi :-) Orang juga dapat menunjukkannya dengan aljabar langsung, menuliskan (seperti pada jawaban saya) dan menghitung elemen kiri atas produk. Tentu saja alasan yang sama, hanya diungkapkan secara berbeda. Terima kasih!
(cosθsinθsinθcosθ)(σmax200σmin2)(cosθsinθsinθcosθ),
amoeba
Dan saya pikir penjelasan geometrik dan perhitungan "langsung" Anda (tanpa matriks) lebih mudah dipahami dan sangat membantu untuk mengembangkan intuisi yang tepat.
amoeba
0

Jika saya menginterpretasikan hal-hal dengan benar, maksud Anda bahwa komponen prinsip pertama (nilai eigen) menjelaskan sebagian besar varian dalam data. Ini dapat terjadi ketika metode kompresi Anda linier. Namun, mungkin ada dependensi non-linear di ruang fitur Anda.

TL / DR: PCA adalah metode linier. Gunakan Autoencoder (pca non-linear) untuk pengurangan dimensi. Jika bagian pembelajaran mesin adalah pembelajaran yang diawasi, maka cukup pantau fungsi kerugian Anda sambil menyesuaikan parameter (hiper) untuk autoencoder. Dengan cara ini Anda akan mendapatkan versi terkompresi yang lebih baik dari data asli Anda.

Berikut ini adalah contoh scikit di mana mereka melakukan pencarian grid untuk menemukan jumlah optimal komponen utama yang harus disimpan (hyper-parameter) menggunakan PCA. Akhirnya mereka menerapkan Regresi Logistik di ruang dimensi bawah: http://scikit-learn.org/stable/auto_examples/plot_digits_pipe.html#example-plot-digits-pipe-py

Protip: Autoencoder tidak memiliki solusi bentuk tertutup (afaik) jadi jika konteks Anda adalah streaming data, ini berarti Anda dapat terus memperbarui autencoder Anda (representasi terkompresi) dan dengan demikian dapat mengkompensasi hal-hal seperti penyimpangan konsep. Dengan pca, Anda harus melatih kembali mode batch dari waktu ke waktu saat data baru masuk.

Untuk memberi beberapa fitur lebih "berat", lihat regularisasi (saya akan mulai dari norma https://en.wikipedia.org/wiki/Norm_(mathematics) ). Anda mungkin juga terkejut betapa miripnya regresi logistik dengan perceptron.

shuriken x blue
sumber
Saya tidak melihat bagaimana ini menjawab pertanyaan OP; jawaban Anda tampaknya sama sekali tidak terkait dengan pertanyaan itu.
amoeba
Karena itu saya bertanya-tanya: adakah cara sederhana untuk hanya memisahkan variansnya dan membaginya dengan PC dengan varian yang lebih sedikit? OP ingin melakukan pengurangan dimensionalitas. Saya menawarkan alternatif untuk menyelesaikan masalahnya, karena pada akhirnya apa yang diinginkan OP tidak menjamin untuk menghasilkan kinerja yang lebih baik kecuali jika kinerja diukur. Bekerja di ruang hilbert / ruang bernorma tidak menjamin hasil yang lebih baik. Mengukur kinerja mengarah ke hasil yang lebih baik.
shuriken x blue