একটি বিশাল, স্পার্স ম্যাট্রিক্সের উপর মাত্রা হ্রাস (এসভিডি বা পিসিএ)


31

/ সম্পাদনা: আরও অনুসরণ করুন এখন আপনি irlba :: prcomp_irlba ব্যবহার করতে পারেন


/ সম্পাদনা: আমার নিজের পোস্টে অনুসরণ করা। irlbaএখন "কেন্দ্র" এবং "স্কেল" আর্গুমেন্ট রয়েছে, যা আপনাকে নীতি উপাদানগুলি গণনা করতে এটি ব্যবহার করতে দেয়, যেমন:

pc <- M %*% irlba(M, nv=5, nu=0, center=colMeans(M), right_only=TRUE)$v


আমার কাছে একটি Matrixমেশিন লার্নিং অ্যালগরিদম ব্যবহার করতে চাই এমন একটি বিশাল স্পারস বৈশিষ্ট্য রয়েছে:

library(Matrix)
set.seed(42)
rows <- 500000
cols <- 10000
i <- unlist(lapply(1:rows, function(i) rep(i, sample(1:5,1))))
j <- sample(1:cols, length(i), replace=TRUE)
M <- sparseMatrix(i, j)

কারণ এই ম্যাট্রিক্সের অনেকগুলি কলাম রয়েছে, তাই আমি এর মাত্রিকতা আরও কিছুটা পরিচালনাযোগ্য কিছুতে কমিয়ে দিতে চাই। আমি এসভিডি সম্পাদন করতে এবং প্রথম এন মূল উপাদানগুলি (5 এখানে দেখানো হয়েছে; আমি সম্ভবত আমার আসল ডেটাসেটে 100 বা 500 ব্যবহার করব) ফেরত দেওয়ার জন্য আমি চমৎকার irlba প্যাকেজটি ব্যবহার করতে পারি :

library(irlba)
pc <- irlba(M, nu=5)$u

তবে, আমি পড়েছি যে পিসিএ করার আগে, ম্যাট্রিক্সকে কেন্দ্র করে নেওয়া উচিত (প্রতিটি কলাম থেকে কলামটি বিয়োগ করতে হবে)। এটি আমার ডেটাসেটে করা খুব কঠিন, এবং আরও ম্যাট্রিক্সের স্পারসিটি নষ্ট করে দেবে।

আন-স্কেলড ডেটাতে এসভিডি সঞ্চালন করা এবং সরাসরি কোনও মেশিন লার্নিং অ্যালগরিদমে খাওয়ানো এটি কতটা খারাপ? ম্যাট্রিক্সের স্পারসিটি সংরক্ষণের সময় আমি কীভাবে এই ডেটা স্কেল করতে পারি তার কোনও কার্যকর উপায় আছে?


/ সম্পাদনা: বি_মিনিয়ারের দ্বারা আমার নজরে আসা একটি "পিসি" সত্যই হওয়া উচিত:

pc <- M %*% irlba(M, nv=5, nu=0)$v 

এছাড়াও, আমি মনে করি whuber এর উত্তর কার্যকরভাবে কার্যকর করা উচিত crossprodফাংশনটির মাধ্যমে , যা খুব কমই ম্যাট্রিক্সে দ্রুত:

system.time(M_Mt <- crossprod(M)) # 0.463 seconds
system.time(means <- colMeans(M)) #0.003 seconds

এখন থেকে আমি সাবস্ক্র্যাক্ট করার meansআগে ভেক্টরকে কী করতে হবে তা আমি নিশ্চিত নই M_Mt, তবে আমি এটি বের করার সাথে সাথে পোস্ট করব।


/ সম্পাদনা 3: প্রক্রিয়াটির প্রতিটি পদক্ষেপের জন্য স্পারস ম্যাট্রিক্স অপারেশন ব্যবহার করে এখানে whuber কোডের সংশোধিত সংস্করণ। আপনি যদি মেমরিতে পুরো স্পারস ম্যাট্রিক্স সঞ্চয় করতে পারেন তবে এটি খুব দ্রুত কাজ করে:

library('Matrix')
library('irlba')
set.seed(42)
m <- 500000
n <- 100
i <- unlist(lapply(1:m, function(i) rep(i, sample(25:50,1))))
j <- sample(1:n, length(i), replace=TRUE)
x <- sparseMatrix(i, j, x=runif(length(i)))

n_comp <- 50
system.time({
  xt.x <- crossprod(x)
  x.means <- colMeans(x)
  xt.x <- (xt.x - m * tcrossprod(x.means)) / (m-1)
  svd.0 <- irlba(xt.x, nu=0, nv=n_comp, tol=1e-10)
})
#user  system elapsed 
#0.148   0.030   2.923 

system.time(pca <- prcomp(x, center=TRUE))
#user  system elapsed 
#32.178   2.702  12.322

max(abs(pca$center - x.means))
max(abs(xt.x - cov(as.matrix(x))))
max(abs(abs(svd.0$v / pca$rotation[,1:n_comp]) - 1))

আপনি যদি কলামগুলির সংখ্যা 10,000 এবং অধ্যক্ষ উপাদানগুলির সংখ্যা 25 তে সেট করেন তবে irlbaভিত্তিক পিসিএ 50 আনুমানিক মূল উপাদান গণনা করতে প্রায় 17 মিনিট সময় নেয় এবং প্রায় 6 গিগাবাইট র্যাম গ্রহণ করে, এটি খুব খারাপ নয়।


Zach, কৌতূহলী যদি আপনি কখনও এটি সমাধান করেন।
বি_মিনার

@ বি_মিনার: মূলত, আমি প্রথমে কেন্দ্র বা স্কেলকে বিরক্ত না করে এসভিডি করছি, কারণ আমার স্পার্স ম্যাট্রিক্সকে ঘন ম্যাট্রিক্সে রূপান্তর না করে এটি করার ভাল উপায় আমি কখনই পাইনি। মূল ম্যাট্রিক্স% *% এসভিডি এর ভি উপাদানটি "নীতি উপাদানগুলি" দেয়। কখনও কখনও, আমি ইগেন মানগুলি, যেমন, ভি% *% ডায়াগ (ডি )গুলিতে "ভাঁজ" করি, তবে আমি আরও ভাল ফলাফল পেতে পারি, যেখানে ডি এসভিডি থেকে ইগেনভ্যালুগুলির ভেক্টর।
জাচ

আপনি নিজেই ভি% *% ডায়াগ (ডি) চিকিত্সা করেন বা এখনও মূল ম্যাট্রিক্স এক্স দ্বারা (যেমন এক্স% *% ভি% *% ডায়াগ (ডি)) দিয়ে গুণিত করেন। আপনি উপরে ম্যাট্রিক্সকে মূল উপাদান স্কোর হিসাবে ব্যবহার করছেন বলে উপরে মনে হচ্ছে?
বি_মিনার

আমি ব্যবহার X %*% v %*% diag(d, ncol=length(d))। এসভিডি-তে থাকা ভি ম্যাট্রিক্স কোনও prcompবস্তুর "ঘূর্ণন" উপাদানটির সমতুল্য , এবং X %*% vবা X %*% v %*% diag(d, ncol=length(d))কোনও xউপাদানের উপাদানকে উপস্থাপন করে prcomp। একবার দেখে একটি নিন stats:::prcomp.default
জাচ

হ্যাঁ, এক্স% *% ভি হ'ল প্রম্পম্প থেকে প্রাপ্ত এক্স উপাদান। দেখে মনে হচ্ছে আপনি যখন আপনার প্রশ্নের মতো ইউ ম্যাট্রিক্স ব্যবহার করেন, আপনি আসলে এক্স% *% ভি% *% ডায়াগ (1 / d) ব্যবহার করছেন।
বি_মিনার

উত্তর:


37

প্রথমত, আপনি সত্যই ডেটাটি কেন্দ্র করতে চান । যদি তা না হয়, পিসিএর জ্যামিতিক ব্যাখ্যা দেখায় যে প্রথম প্রধান উপাদানটি মাধ্যমের ভেক্টরের কাছাকাছি থাকবে এবং পরবর্তী সমস্ত পিসিগুলি এর সাথে অরথোগোনাল হবে, যা তাদের প্রথম ভেক্টরের নিকটবর্তী হতে পারে এমন কোনও পিসি আনুমানিক থেকে আটকাবে will আমরা আশা করতে পারি যে পরবর্তীকালের বেশিরভাগ পিসি প্রায় সঠিক হবে, তবে সম্ভবত এটির বেশিরভাগ পিসি - সর্বাধিক গুরুত্বপূর্ণ - বেশ ভুল হবে be

তো এখন কি করা? পিসিএ ম্যাট্রিক্স একটি একবচন মান পচানি মাধ্যমে আয় । প্রয়োজনীয় তথ্য এক্স এক্স ′ এ অন্তর্ভুক্ত থাকবে , যা এই ক্ষেত্রে 10000 বাই 10000 ম্যাট্রিক্স: এটি পরিচালনাযোগ্য হতে পারে। এর গণনায় পরের সাথে একটি কলামের ডট পণ্যগুলির প্রায় 50 মিলিয়ন গণনা জড়িত।XXX'1000010000

ওয়াইজেড500000এনmYmজেড1n1

(YmY1)(ZmZ1)=YZmZ1YmY1.Z+mZmY11=YZn(mYmZ),

mY=1Y/nmZ=1Z/n

XXYZ10000XX


উদাহরণ

Rget.colXprcomp

m <- 500000 # Will be 500,000
n <- 100    # will be 10,000
library("Matrix")
x <- as(matrix(pmax(0,rnorm(m*n, mean=-2)), nrow=m), "sparseMatrix")
#
# Compute centered version of x'x by having at most two columns
# of x in memory at any time.
#
get.col <- function(i) x[,i] # Emulates reading a column
system.time({
  xt.x <- matrix(numeric(), n, n)
  x.means <- rep(numeric(), n)
  for (i in 1:n) {
    i.col <- get.col(i)
    x.means[i] <- mean(i.col)
    xt.x[i,i] <- sum(i.col * i.col)
    if (i < n) {
      for (j in (i+1):n) {
        j.col <- get.col(j)
        xt.x[i,j] <- xt.x[j,i] <- sum(j.col * i.col)
      }    
    }
  }
  xt.x <- (xt.x - m * outer(x.means, x.means, `*`)) / (m-1)
  svd.0 <- svd(xt.x / m)
}
)
system.time(pca <- prcomp(x, center=TRUE))
#
# Checks: all should be essentially zero.
#
max(abs(pca$center - x.means))
max(abs(xt.x - cov(x)))
max(abs(abs(svd.0$v / pca$rotation) - 1)) # (This is an unstable calculation.)

বিস্তারিত উত্তরের জন্য আপনাকে ধন্যবাদ। এর একটি সুবিধা irlbaহ'ল আপনি nuপ্রথম এন নীতি উপাদানগুলিতে অ্যালগরিদম সীমাবদ্ধ করতে নির্দিষ্ট করতে পারেন , যা এর কার্যকারিতা ব্যাপকভাবে বৃদ্ধি করে এবং (আমি মনে করি) XX এর ম্যাট্রিক্সের গণনাটি বাইপাস করে।
Zach

1
100005000005×1091000010000108irlba

আমি মনে করি পরেরটি। =)। সুতরাং আমার স্পার্স ম্যাট্রিক্সে প্রতিটি জোড় কলামের জন্য ডট পণ্য গণনা করা দরকার, বিন্দু পণ্য colMeansম্যাট্রিক্স থেকে স্পার্স ম্যাট্রিক্সের বিয়োগ করতে হবে , তারপরে ফলাফলটি দিয়ে র্বা চালাব?
জাচ

XXRX

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