Mais conteúdo relacionado
Semelhante a Knn発表資料(R) (20)
Knn発表資料(R)
- 12. 1班 資料
1-3.1 relationshipの削除
12
> tapply(salary$marital.status, salary$relationship, table)
$Husband
Married-AF-spouse Married-civ-spouse
12 17737
$`Not-in-family`
Divorced Married-civ-spouse Married-spouse-absent
3267 21 296
Never-married Separated Widowed
6400 567 770
$`Own-child`
Divorced Married-AF-spouse Married-civ-spouse
409 1 129
Married-spouse-absent Never-married Separated Widowed
58 6089 126 24
# などなど
- 19. 1班 資料
マルチクラス分類
黒板で説明
19
category <- c(2,3,5,6,7,8,10)
for(i in category){
for(j in levels(salary.c[, i])[-1]){
salary.c[, paste(colnames(salary.c)[i], j, sep = "-")] <- salary.c[, i] == j
}
}
salary.c <- salary.c[,-category]
- 25. 1班 資料
最適なKを選ぶ
• 問題点
• 時間がかかりすぎる問題
• knn(k = all)
• 理論時間
• 54.64*32,968
• =1,801,371sec
• =500時間 (21日)
(※ノートPCなら916時間-38日)
25
- 26. 1班 資料
使用するマシン
OS: Windows 10
CPU: 3.60GHz
Intel Core i7 – 9700K (8コア 8スレット)
SSD: 4TB
HHD: 2TB
GPU: RTX2070 SUPER
( Intel UHD Graphics 630 )
メモリ: 32GB
26
- 27. 1班 資料
KNNの高速化
インデックスを距離が近い
順に並べたdata.frame
を作成する
test_1 test_2 test_3
3070 4012 5011
27 15 27
15 10721 15
1678 98 4021
13 2012 307
5612 37 21
10720 10989 13
… … …
予測と実際を見比べて
評価関数のグラフ
を作成する
kを作業可能な量で無作為
抽出して、多数決表
を作成する(全探索はしない)
test_1 test_2 test_3
3070 4012 5011
27 15 27
15 10721 15
1678 98 4021
13 2012 307
5612 37 21
10720 10989 13
… … …
K = 6を使用
K = {6,13, 29, 93, 107...
- 28. 1班 資料
①距離計算の高速化
28
インデックスを距離が近い
順に並べたdata.frame
を作成する
test_1 test_2 test_3
3070 4012 5011
27 15 27
15 10721 15
1678 98 4021
13 2012 307
5612 37 21
10720 10989 13
… … …
knn.calc <- function(test, train) {
distance <- function(x, y) {
sqrt(sum((x - y)^2))
}
rank.dist <- function(x, train) {
order(apply(train, MARGIN=1, distance, x))
}
as.data.frame(apply(test, MARGIN=1, rank.dist, train))
}
tic()
knn.calc(salary.test[1:10, ], salary.train)
toc() #desk 1.85sec
forやlapplyなどの繰り返し関数を使う場合
理論値
1.85*10989 = 2033sec
→33分かかる計算になる
- 29. 1班 資料
①距離計算の高速化
29
インデックスを距離が近い
順に並べたdata.frame
を作成する
test_1 test_2 test_3
3070 4012 5011
27 15 27
15 10721 15
1678 98 4021
13 2012 307
5612 37 21
10720 10989 13
… … …
tic()
knn.db <- lapply(1:test.len, function(i)
sqrt(rowSums((train.mat - t(matrix(test.mat[i, ], nrow =
dim(salary.train)[2] , ncol = train.len)))^2))
)
knn.db <- lapply(knn.db, function(x) order(x))
knn.db <- data.frame(knn.db)
toc() #desk 311.99sec, note 798.52sec
改良の余地はあるが、マトリックス計算をすることで、それぞれの計算時間を
定数時間化 𝑇 𝑁 = 𝑂(1)とすることが可能になり、時間が6倍加速した。
実際には、𝑇 𝑖 ∗ 𝑗 = 𝑂 𝑖 ∗ 𝑗 → 𝑇 𝑖 ∗ 𝑗 = 𝑂 𝑖 (𝑖はtest. data, jは𝑡𝑟𝑎𝑖𝑛. 𝑑𝑎𝑡𝑎)
実質値
311.99sec
→5分 < 33分
しかし、knnが54secであるため、さらにあと6倍程度加速する必要があるようだ。
- 35. 1班 資料
②Kによる処理を高速化
35
kを作業可能な量で無作為
抽出して、多数決表
を作成する
test_1 test_2 test_3
3070 4012 5011
27 15 27
15 10721 15
1678 98 4021
13 2012 307
5612 37 21
10720 10989 13
… … …
K = 6を使用
K = {6,13, 29, 93, 107...
k.vec <- 1:dim(salary.train)[1]
stu <- round(1 + log2(dim(salary.train)[1]))
k.dat <- data.frame(matrix(k.vec[1:(round(dim(salary.train)[1]/stu)*stu)],
nrow = stu))
k.ran <- sapply(k.dat, function(x) x[sample(1:stu, 1)])
最適なKを探す前に、すべてのKで試行すれば、到底終わらない。
→そこで、Kを無作為抽出することとする。
評価関数を正規分布と仮定したとき、スタージェスの公式からKベクトルの
幅が16のときが最もきれいに書けると算出れたので、16ずつ無作為抽出し
ていくこととする。
- 38. 1班 資料
②K処理の高速化
38
knn.own <- function(data, test.labels, k, dev){
#warning
if(sum(k == 1) > 0) {
warning("you must not use 1 in k !")
return(NA)
}
if(length(k) %% dev > 0) {
warning("you must use a numeric which k can be devided evenly by in dev !")
return(NA)
}
#preparation
bin <- ifelse(data == "undr_50k", 1, 0)
bin.dev <- lapply(1:(dev-1), function(x) colSums(data.frame(bin[1:(k[length(k)/dev*x]-1), ])))
label <- matrix(ifelse(test.labels == "undr_50k", 1, 0), nrow = length(test.labels), ncol = length(k)/dev )
#k
f.round <- lapply(1:dev, function(x) data.frame(lapply((k)[(length(k)/dev*(x-1)+1):(length(k)/dev*x)] ,
function(y){ if(x == 1){round(colSums(bin[1:y, ]) / y)}
else {round((bin.dev[[x-1]] + colSums(bin[((k)[length(k)/dev*(x-1)]):y, ]))/y)}})))
#evaluation
f.output <- c()
for(i in 1:dev){
f.output <- c(f.output, colSums(f.round[[i]] == label) / dim(label)[1] )
}
names(f.output) <- paste("k = ",k , sep="")
#result
f.output
}
- 40. 1班 資料
②K処理の高速化
40
tic()
output <- knn.own(knn.labels, salary.test.labels, k = k.ran, dev = 10)
toc() #desk 113.91sec
一般的なKNN()関数で実行した場合、
理論値
31時間
knn.oun()関数で実行した場合、
実質値
131.91 + 311.99 = 443.9sec
112558.4/443.9 = 254倍加速した
- 43. 1班 資料
③評価関数
tic()
output <- knn.own(knn.labels,
salary.test.labels, k = k.ran, dev
= 10)
toc() #desk 113.91sec
plot(x = k.ran, y = output,
type = "l")
names(output)[max(sapply(
output, function(x) x)) ==
as.numeric(output)]
#[1] "k = 170"
43
- 44. 1班 資料
③評価関数
44
tic()
output2 <- knn.own(knn.labels,
salary.test.labels, k = 2:1000, dev =
3)
toc() #desk 16.86sec
plot(x = 2:1000, y =
output2, type = "l")
names(output2)[max(sapply
(output2, function(x) x)) ==
as.numeric(output2)]
#[1] "k = 166" "k = 170" "k = 172"