2018年11月21日 星期三

[R語言] Coursera R Programming Week 3 Assignment超白話解釋


有鑑於這是第一次學習程式語言(高中生科課那種玩玩的不算XD),充滿不熟悉和不確定性,於是希望藉由紀錄學習過程,可以幫助往後自己的學習,然後我自己的邏輯思考跟抽象思考能力不是很好,過去在學習數學和科學理論時常碰壁或卡關,因此希望可以利用一些方法去釐清問題,並想辦法把這些事物轉化成自己可以理解和記憶的形式,希望多少也可以幫助到跟我一樣初學R的夥伴。

這次Coursera的作業是要依樣畫葫蘆寫出一個R function來緩存被計算過的數值,以減少電腦重複計算所需要的時間和空間,尤其是當被計算物件相對複雜時。僅僅是依樣畫葫蘆其實不難完成這個作業,但我看了很久還是不知道這個function是怎麼寫出來的?為什麼這樣寫?

首先,Simon Sinek提出的黃金思維圈(Golden circle)是個好東西,讓我們從Why-How-What的結構先分析這個問題。

Purpose?
Write an R function that is able to cache potentially time-consuming computations

Why?
If an object is complex, and its computation value needs to be reused again, cache the value, so that it can be looped up in the cache rather than recomputed.

cache > recomputation

How?
Take advantage of the scoping rules of R & how they can be manipulated to preserve state inside of an R object

What?
Example:
makeVector <- function(x = numeric()) {        ## makeVector creates a special "matrix"
        m <- NULL                                        ## which is really a list containing a
        set <- function(y) {                             ## function to set the value of the vector
                x <<- y
                m <<- NULL
        }
        get <- function() x                              ## get the value of the vector
        setmean <- function(mean) m <<- mean  ## set the value of the mean
        getmean <- function() m                      ## get the value of the mean
        list(set = set, get = get,
             setmean = setmean,
             getmean = getmean)
}

cachemean <- function(x, ...) {                     ## cachemean calculates the mean of
        m <- x$getmean()                              ## the special "matrix" created above
        if(!is.null(m)) {                                    ## check if the mean has been calculated
                message("getting cached data")   ## if so, get the mean from the cache
                return(m)                                   ## and skips computation
        }
        data <- x$get()                                  ## Otherwise, it calculates the mean of
        m <- mean(data, ...)                           ## the data, and sets the value of the
        x$setmean(m)                                    ## mean in cache via the setmean
        m                                                     ## function
}

Assignment:
makeCacheMatrix <- function(x = matrix()) {
  i <- NULL
  set <- function(y) {
    x <<- y
    i <<- NULL
  }
  get <- function() x
  setinverse <- function(inverse) i <<- inverse
  getinverse <- function() i
  list(set = set, get = get,
       setinverse = setinverse,
       getinverse = getinverse)
}

cacheSolve <- function(x, ...) {
  i <- x$getinverse()
  if(!is.null(i)) {
    message("getting cached data")
    return(i)
  }
  data <- x$get()
  i <- solve(data, ...)
  x$setinverse(i)
  i
}

經過說明後我僅能看得懂片段的function,但針對細節的設定(尤其是為什麼要makeCacheMatrix)還是不清楚,充滿疑問,所以我先把問題記下來,然後再從看得懂的,或最簡單的開始前後推敲,不需要按照順序理解。

黑人問號:
問題1: 透過這兩個function,matrix實際做了哪些事?
問題2: 這兩個function如何緩存計算值?
問題3: 為什麼要定義makeCacheMatrix?其中為什麼要定義這麼多function?目的是?

原始想法:
i <- solve(a, ...)
i                             => 建立function想要把他記憶下來
i <- solve(a, ...)         => 建立function想要省略重複計算
i                             => 建立function想要把他從記憶中提取出來

問題4: 如何把它擴張成可以達成使用目的的function?需要幾個function?一個夠嗎?

先看比較容易懂的cacheSolve function(比較不懂的部分標紅色):
cacheSolve <- function(x, ...) {
  i <- x$getinverse()                         ## 提取被計算與緩存過的matrix inverse值
  if(!is.null(i)) {                                  ## 如果matrix inverse值不是NULL(空值),表示已
    message("getting cached data")    ## 有緩存的值,呈現getting cached data的訊息
    return(i)                                      ## 並回報matrix inverse的值
  }
  data <- x$get()                             ## 若是NULL,則叫出matrix值
  i <- solve(data, ...)                         ## 計算inverse值
  x$setinverse(i)                               ## 將計算好的inverse值賦值給欲緩存的變數i
  i                                                  ## 回報matrix inverse的值
}
小結:這個function主要作用是判斷matrix inverse是否經過計算,若有的話直接提取緩存值,若無的話計算後把結果透過setinverse()緩存,下次就可以用getinverse()提取。

接著看makeCacheMatrix function(比較不懂的部分標紅色):
makeCacheMatrix <- function(x = matrix()) {  ## 把matrix建立成一個特別的list
  i <- NULL                                                ## 定義變量i,紀錄matrix inverse的值
  set <- function(y) {                                   ## 定義set function,指定一個新的matrix
    x <<- y                                                 ## 在主環境中,當有新的matrix時,
    i <<- NULL                                            ## 重新設定變量i為NULL(空值)
  }
  get <- function() x                                    ## 定義get function,回報matrix本身
  setinverse <- function(inverse) i <<- inverse ## 定義setinverse function,用來指定
                                                                ## i值,賦值計算值為變數i 而不再是NULL
  getinverse <- function() i                          ## 定義getinverse function,回報i值
  list(set = set, get = get,                            ## 回報一個屬於matrix的list
       setinverse = setinverse,                       ## 包含set, get matrix和 set, get matrix
       getinverse = getinverse)                      ## inverse四個物件,提供cacheSolve函式
}                                                             ## 引用

小結:這個function主要作用是把matrix拆成四個物件,以list的方式呈現,供下一個cacheSolve function引用。為什麼要定義這四個物件?少幾個有關係嗎?以實際計算、緩存、提取的需求來說,後三個是必要的,但是set()並沒有出現在cacheSolve function扮演任何角色,經過實際跑程式驗證:沒有定義set()並不會造成運作失敗。那為什麼要定義set()?這個我...就不知道了。

實例分析:
a <- matrix(c(1, 2, 3, 4), nrow = 2)              ## 建立一個matrix叫做a
alist <- makeCacheMatrix(a)                      ## 轉化matrix為list來包含需要使用的物件
alist                                                         ## 看看alist長什麼樣子
$set                                                        ## set function,定義新的matrix的i值
function (y)
{
    x <<- y
    i <<- NULL
}
<bytecode: 0x10f859df0>
<environment: 0x10d9bcd90>

$get                                                        ## get function,回報matrix a本身
function ()
x
<bytecode: 0x10e6ef1c8>
<environment: 0x10d9bcd90>

$setinverse                                              ## setinverse function,用來緩存i值
function (inverse)                                      ## 賦值計算結果給變數i,讓i不再是NULL
i <<- inverse
<bytecode: 0x110106750>
<environment: 0x10d9bcd90>

$getinverse                                              ## getinverse function,用來提取i值
function ()                                                ## 可能是NULL或是被緩存的值
i
<bytecode: 0x10e7636d0>
<environment: 0x10d9bcd90>

cacheSolve(alist)                                       ## 第一次計算matrix inverse
     [,1] [,2]                                                ## i為NULL,需計算並且把計算結果緩存
[1,]   -2  1.5                                             
[2,]    1 -0.5

cacheSolve(alist)                                       ## 第二次計算matrix inverse
getting cached data                                   ## 已有緩存值所以不必計算,直接提取
     [,1] [,2]
[1,]   -2  1.5
[2,]    1 -0.5

結論:這個程式語言是透過function、loop的設計和R的Lexical Scoping rules來達到目的,思考的方向可以從易懂的部份著手,前後推敲,找出每一個編程的用意,想一下為什麼順序要這樣安排,實際操作怎麼運行,有疑問或其他想法可以自己嘗試。學習過程: 參考範例 -> 問問題&記錄問題 -> 尋找為什麼 -> 串連一連串的為什麼來解釋整個故事 -> 練習活用

2018年11月14日 星期三

[健身] 邁向良好體態的第一步:鍛鍊核心肌群


不知道有沒有人跟我一樣,長期有駝背、姿勢不良的習慣,久而久之產生了許多問題:包括脊椎側彎、長短腳、肩頸跟下背部酸痛。

大概是這一兩年發現這樣的情形越來越嚴重,左腳甚至會麻不舒服,某些動作做起來可以聽到骨頭嘎嘎作響的聲音,雖然還沒看醫生,但感覺有坐骨神經有壓迫到左腳神經的可能。

於是乎!為了矯正和鍛煉良好的體態,加上最近也比較有空,我報名了健身房的課程和教練課。才不到短短半個月,已經感覺身體開始在改變了,耶!

首先是體態的部分,想要維持良好體態,需要身體各部位的肌肉平衡。身體最重要最大面積的肌群就是核心肌群了,是位置在橫隔膜以下骨盆底以上的肌群,包含腹肌、背肌、臀肌、大腿肌,是負責保護、穩定脊椎的重要肌群。若缺乏鍛煉,將無法提供脊椎足夠的支撐力,造成脊椎壓力過大,容易使腰背部在活動時扭傷。長期肌力不足,也會導致駝背和常見的下背疼痛。

透過教練的講解,頓時覺得豁然開朗和充滿希望R,才知道我以前的認為的抬頭挺胸是錯的!以前總認為抬頭挺胸就是把胸部挺出去、肩膀外擴,但是單純地利用脊椎彎曲的力量把胸部挺出,小腹也會跟著凸出,骨盆前傾翹屁股,在這樣脊椎不是直的情形會導致很多不舒服的情況。正確的抬頭挺胸是靠背肌的力量把肩胛骨下壓,小腹用力收縮,讓脊椎呈現垂直,胸部自然挺起。另外我還有聳肩跟肩膀內旋的問題,因為不會背肌出力,常會用錯成肩膀出力,漸漸的身體前側的肌肉把肩膀往前拉,一樣可以透過正確的抬頭挺胸改善!

有一個很簡單的練習方法就是背面靠牆壁站,身體要完全貼在牆面上,腰部的部分只能有一個手掌的距離,距離太遠的話就代表你用錯方法了,脊椎是彎的,所以要記得收小腹。站的時候觀察身體哪些地方在用力,那些用力的肌群就是缺乏鍛煉的肌群!練習直到站的時候很輕鬆自然,不需要特別用力,就可以正式跟駝背say bye bye啦!

因為我最想改掉的就是駝背,所以這一個月來訓練的主力放在背肌(背闊肌和下斜方肌)和腹肌!下次就來介紹如何鍛鍊背肌吧!





統計學 | 什麼是變方分析ANOVA? ANOVA的概念與統計檢定量的推導

什麼是 ANOVA? 在前面的統計學章節,我們學到單變量和兩變量的假設檢定,假設我們想要比較三個以上的樣 本 是否有差異,這時候就要使用 ANOVA了。 ANOVA, analysis of variance, 變方分析,雖然名為「變方」分析,但其實是用來檢定三個以上的樣本...