sweep関数の使い方を忘れがちなので自分へのメモ
まとめ
sweep関数の
- MARGIN = 1の時は
- i 行目のそれぞれの値に対してSTATSの i番目の値をFUNと二項演算する
- MARGIN = 2の時は
- j 列目のそれぞれの値に対してSTATSの j番目の値をFUNと二項演算する
お気持ち
行平均の引き算のお気持ち
- sweepで1行目の行平均を引き算したいとき、1行目の各要素から引き算する値はスカラーな行平均。
- sweepで2行目の行平均を引き算したいとき、2行目の各要素から引き算する値はスカラーな行平均。
- ...
となる。sweep(mat, MARGIN = 1, ...)の時、1行目ベクトルからSTATSベクトルを減算し、2行目ベクトルからSTATSベクトルを減算し・・・とはならないので要注意。 忘れたら行平均の減算、列平均の減算を思い出そう。
確認コード
MARGIN = 1の場合
> # 行列を生成し > (m <- matrix(c(3,1,4,1,5,9,2,6,5,3,5,9),ncol=4)) [,1] [,2] [,3] [,4] [1,] 3 1 2 3 [2,] 1 5 6 5 [3,] 4 9 5 9 > # 行平均を確認 > rowMeans(m) [1] 2.25 4.25 6.75 > # 行平均を各行から引く > sweep(m, MARGIN = 1, STATS = rowMeans(m), FUN = "-") [,1] [,2] [,3] [,4] [1,] 0.75 -1.25 -0.25 0.75 [2,] -3.25 0.75 1.75 0.75 [3,] -2.75 2.25 -1.75 2.25 >
MARGIN = 2 の場合
> # 列平均を確認 > colMeans(m) [1] 2.666667 5.000000 4.333333 5.666667 > # 列平均を各列から引く > sweep(m, MARGIN = 2, STATS = colMeans(m), FUN = "-") [,1] [,2] [,3] [,4] [1,] 0.3333333 -4 -2.3333333 -2.6666667 [2,] -1.6666667 0 1.6666667 -0.6666667 [3,] 1.3333333 4 0.6666667 3.3333333 >
となる。
雑だけどirisを機械学習する
まえがき
Data Science: Machine Learningを受講しています。今までのR BasicsやVisualizationに比べて課題が多くてなかなか進まないです。8月中には完了させたいですね。
本題ですが、今回は「雑だけどirisを機械学習する」ということで、とりあえずcaret使って機械学習を動かしてみようと思います。理論が分からないと機械学習なんて触っちゃダメだろーと思っていましたが、まぁまずはtryですよ。
ソースコード
# テストデータで10行 # 訓練データはそれ以外 ind <- sample(iris %>% nrow(), size = 10, replace = FALSE) iris_test <- iris[ind, ] iris_train <- iris[-ind,] # trainのメソッドを欲張りセットでこしらえる methods <- list("lda","qda","knn","rf","nnet") # Accuracyを出す accuracies <- map_dbl(methods, function(me){ trained <- train(Species ~ ., data = iris_train, method = me ) predicted <- predict(trained, iris_test) confusionMatrix(data = predicted, reference = iris_test$Species)$overall["Accuracy"] }) # ベクトルに名前をつけて names(accuracies) <- methods # 表示 accuracies
結果
2,3回ぶん回しましたがだいたい8~9割ぐらいのAccuracyが出ました。
> accuracies lda qda knn rf nnet 1.0 1.0 0.8 0.8 0.9
2次元正規分布のデータから2通りの方法で回帰直線を引く
タイトルの通りです。
lm
で単回帰直線- 平均と分散共分散からE[Y|X=x] *1を計算
の2通りで回帰直線を引きます。
コード
library(MASS) library(scales) options(digits = 3) # 平均 mx <- 10 my <- 22 # 分散 Sx <- sqrt(9) Sy <- sqrt(16) Sxy <- sqrt(9.6) # サンプルサイズ n <- 10000 # 平均ベクトル M <- c(mx, my) # 分散共分散行列 Sig <- c(Sx^2,Sxy,Sxy,Sy^2) %>% matrix(2,2) z <- MASS::mvrnorm(n, mu = M, Sigma = Sig ) # dev.off() # 散布図プロット plot(z[,2] ~ z[,1], xlab = "x", ylab = "y",col = c(alpha('orange', 0.2)) ) # 単回帰直線(青) lm.z <- lm(z[,2] ~ z[,1]) coef(lm.z) abline(lm.z, col ="blue", lwd = 2, lty = 2) # E[Y|X = x]で直線を引く(赤) list("Intercept" = my - mx * (Sxy/(Sx*Sy))*(Sy/Sx), "Slope" = (Sxy/(Sx*Sy))*(Sy/Sx) ) %>% unlist() abline(my - mx * (Sxy/(Sx*Sy))*(Sy/Sx), (Sxy/(Sx*Sy))*(Sy/Sx), col="red", lwd = 3, lty = 2)
結果
だいたい一致しました。青が単回帰直線、赤がE[Y|X = x]です。
- lmでの係数
> coef(lm.z) (Intercept) z[, 1] 18.552 0.344
- E[Y|X = x]での係数
> list("Intercept" = my - mx * (Sxy/(Sx*Sy))*(Sy/Sx), "Slope" = (Sxy/(Sx*Sy))*(Sy/Sx) ) %>% unlist() Intercept Slope 18.557 0.344
参考
改訂版 日本統計学会公式認定 統計検定2級対応 統計学基礎 のp.86 (2.9.18)
*1:母数から計算しているのでおそらく母回帰直線、と思われる。
標準誤差は統計量の標準偏差であることを確かめる
やること
離散型確率分布
X | p |
---|---|
17 | 0.3 |
-1 | 0.7 |
に於いて、大きさn=100の標本を抽出する時、
- 和S の標本分布について、Sの平均、標準誤差
- 平均M の標本分布について、Mの平均、標準誤差
をそれぞれ
- 計算
- モンテカルロ シミュレーション
によりそれぞれ求める。
計算:離散型確率分布から分かること
Xの期待値・分散・標準偏差はそれぞれ、
であるから、サンプルサイズn=100における、
和S = の標本分布について
- 各は として、
- Sの期待値:=
- Sの標準誤差:=
平均M = の標本分布について
- 各は として、
- Mの期待値:=
- Mの標準誤差:=
である。
モンテカルロ シミュレーション
共通の設定
X <- c(17,-1) #確率変数 p <- c(0.3,0.7) #確率 n <- 100 #サンプルサイズ B <- 10000 #サンプル"数"
和の分布
# 和の分布 #### S <- replicate(B,{ sum(sample(X,size=n,replace=TRUE,prob=p)) }) # 結果 c(平均値 = mean(S), 標準誤差 = sd(S))
> c(平均値 = mean(S), 標準誤差 = sd(S)) 平均値 標準誤差 438.75620 82.56416
平均値の分布
# 平均値の分布 M <- replicate(B,{ mean(sample(X,size=n,replace=TRUE,prob=p)) }) # 結果 c(平均値 = mean(M), 標準誤差 = sd(M) )
> c(平均値 = mean(M), 標準誤差 = sd(M) ) 平均値 標準誤差 4.4000180 0.8259942
おわりに
やってることは例によってChapter 13 Probability | Introduction to Data Scienceで学んだことです。標準誤差は統計量の標準偏差
であるってのは数式だけだといまいちピンとこないのですが、このようにRでシミュレーションするとだいたい同じになるので腑に落ちました。replicate
関数の第一引数にサンプル"数"を、第二引数には統計量(の式)を記述することによって、統計量の分布をシミュレーションすることができます。便利です。
おまけ: replicate関数の練習
(これを最初に書くべきだったのでは?)サイコロを2回投げて出た目の和が7となる確率、をRで求める。
共通
saikoro <- 1:6 # サイコロ B <- 10000 #サンプル"数"
組み合わせで割り算する素朴な求め方
# サイコロを2回投げた時の組み合わせ saikorokumi <- expand.grid(saikoro,saikoro) # 和が7になる組み合わせ ÷ サイコロを2回投げた時の組み合わせの総数 sum( apply(saikorokumi,1,sum) == 7 ) / nrow(saikorokumi)
> sum( apply(saikorokumi,1,sum) == 7 ) / nrow(saikorokumi) [1] 0.1666667
2回投げて出た目の和の分布
# サイコロを2回投げて出た目の和の分布 kiroku <- replicate(B,{ sum(sample(saikoro,2,replace=TRUE)) }) # 和が7となる確率 mean(kiroku == 7)
> mean(kiroku == 7) [1] 0.1659
2回投げて出た目の和が7となるか否かの分布
# サイコロを2回投げて出た目の和が7となるか否かの分布 kiroku2 <- replicate(B,{ sum(sample(saikoro,2,replace=TRUE)) == 7 }) # 和が7となる確率 mean(kiroku2)
> mean(kiroku2) [1] 0.1684
確率変数の取りうる値が2つの時の離散型確率分布の標準偏差を求める公式
結論
確率変数においてそれぞれ確率をとる時、標準偏差SD(X)は
となる。ここで||は絶対値の記号である。
どこで見つけたか
edXのprobabilityの教科書?であるChapter 14 Random variables | Introduction to Data Science や ここである。
計算例
離散型確率分布が以下の表、
X | p |
---|---|
17 | 0.3 |
-1 | 0.7 |
で与えられているとする。
まずは期待値・分散・標準偏差を計算し、最後に公式を用いて標準偏差を計算して2つの標準偏差が一致することを確かめる。
期待値
分散
標準偏差
分散のルートを取って求めると、
一方、冒頭の公式で求めると、
証明
確率分布は、においてそれぞれ確率であると設定する。この時、期待値は
で計算できる。
分散は、
と計算できるがここで、を消去すると、とはそれぞれ、
となる。これを分散の式に代入すると、
ゆえに、より
を得る。
Rで文字列→数値に変換する際、NAs introduced by coercionが出て困った時のtips
次のような変換を考えます。
- "1名" → 1
- "2名" → 2
- "なし" → 0
- "調査中" → NA
これをdplyrのパイプの中でmutate( case_when(...) )
を駆使して実行していたのですが、エラーとなってしまいました。
データフレーム(見栄えのためtibble)
mydf <- tibble( 同居家族 = c("1名","2名","なし","調査中") )
ダメな例
mydf %>% mutate( 同居家族数 = case_when( 同居家族 == "なし" ~ 0 , 同居家族 == "調査中" ~ NA_integer_ , str_detect(同居家族,"名") ~ as.numeric( str_remove(同居家族,"名") ) ) )
上を実行すると次のようなErrorが出ます。
Error: Problem with `mutate()` input `同居家族数`. x must be an integer vector, not a double vector. ℹ Input `同居家族数` is `case_when(...)`. Run `rlang::last_error()` to see where the error occurred. In addition: Warning message: In eval_tidy(pair$rhs, env = default_env) : NAs introduced by coercion
ググってみると、なんとなく似たようなissueが上がっておりました。
頑張って読んでみると、case_when
で分岐してもas.numeric( str_remove(同居家族,"名") )
が実行されるのはstr_detect(同居家族,"名")
の時のみではないっぽいことがわかりました。ということで結局、as.numeric()
するときに数値に変換できない文字列が入っていたためエラーになっていた、というわけです。
改善策
改善策としては、面倒臭がらず列を数字に変換できる文字列に一旦変換したのちに、改めてas.numeric()
してあげれば良いわけです。
mydf %>% mutate( 同居家族数 = case_when( 同居家族 == "なし" ~ "0" , 同居家族 == "調査中" ~ NA_character_ , str_detect(同居家族,"名") ~ str_remove(同居家族, "名") ), 同居家族数 = as.numeric(同居家族数) )
実行結果
edXのHarvardX's Data Scienceを受講しています。
edXのHarvardX's Data Scieceとは? → HarvardX Data Science Professional Certificate | edX
とりあえずR Basicsが終わってVisualizationのIntroの途中まで来ました。2年前も同じコースを受講したのですが、その時は途中でドロップアウトしてました・・・。モチベーションとやる気があると意外とすんなりできちゃうもんですね。
感想を書いておきます。
読んでおくと良いもの
これです → Introduction to Data Science
R Basicsを受講すると良さそうな人
- 英語で説明されても頑張れる人
- 字幕もあるしスピードも変えられるので、実はそんなに身構えなくても大丈夫?でした
- Rやdata vizで使う単語を知っていると良いカモです
- Rを触ったことがある人
- RStudioをインストールしている人
- dplyrを触ったことがある人
- 周りでRを使っている人がいない人
- 独習者
- Rを体系的に学び通したい人
難しいと感じた所
- AssignmentのQuestionの英語を読み解くのが難しかったです。
よく使った関数
- class()
- str()
- names()
- match()
- which()
というかんじです。7月中にVisualizationとProbabilityを終わらせたいです。
座標軸の回転
これなら分かる最適化数学のp.48にある座標軸の回転について、回転の式を導出してみます。
x成分の計算
と、 よりとなります。
y成分の計算
とよりとなります。
まとめると
以上より、、を行列形式にまとめて、
となります。