Tag

2017年12月31日 星期日

Git 教學影片系列

故事是這樣子的,自己大概三四年前開始使用git,一路用到現在,對 git 相關的功能算是相當熟悉,有時也會負責教其他人使用 git,自己的 blog 上其實也留了不少 git 相關的文章:
https://yodalee.blogspot.tw/search/label/git
大約兩個禮拜前突發奇想,反正都要教,乾脆就錄個影片,以後只要貼影片給別人看,不只教認識的,還能教虛擬世界中「沉默的多數」(誤),想著想著稍微規劃了一下,好像還真的有點模樣,於是就開始了我變身網(ㄈㄟˊ)紅(ㄓㄞˊ)的第一步。

最後確定的版本有以下幾集的影片,一部是相關的功能,順便還會介紹一些社群習慣或是我自己的習慣,講得滿雜的,也有些出錯的地方:

Ep. 1 安裝與設定
Ep. 2 Add, commit:50/72 rule, gitignore, commit hash, DAG
Ep. 3 如何指定一個 commit:hash, HEAD, ^ ~, reference, show, log, diff, diff --staged
Ep. 4 patch add and amend
Ep. 5 branch, checkout, merge:解衝突
Ep. 6 Rebase:rebase -i,解衝突
Ep. 7 遠端開發,使用 github:用 gitgraph.js 的開發經驗,來說明如何使用 github
Ep. 8 stash
Ep. 9 format-patch, apply, am, cherry-pick 各種搬移工作的方法
Ep. 10 bisect, blame
Ep. End ending:講一下一些沒提的東西

自己做起來就發現,想當 youtuber 要費的功夫真的超級大,除了初期收集資料跟準備材料,投影片跟 demo 用的 project,還要確認要講的內容沒有錯誤;真正錄的時候可能還要多錄幾遍,確定哪裡說不好要改進,如果不小心說錯了,要重頭再錄一次,事後還要上傳 Youtube 修改影片資訊等等。
像後來,就發現我在安裝的那章其實有個錯誤,Windows系統不能只安裝 Tortoise git,還要安裝 git 才行…不過暫時還沒想到怎麼去修正它(yay;如果像那些網紅一樣還要加後製,那成本真的超級大,我猜不組個小團隊其實是很難撐起來的

總之這些是最後的成品,收到一個 youtube 播放清單中:
https://www.youtube.com/playlist?list=PLlyOkSAh6TwcvJQ1UtvkSwhZWCaM_S07d
或者下面是嵌入式的影片:

自己回想起來其實花了非常多時間在錄這些教學影片,還去買了新的麥克風,錄製跟剪輯影片分別使用 obs 跟 ffmpeg 剪輯指令,因為加特效太麻煩,所以就沒加特效 =w=,希望這些影片能對大家有所幫助。
雖然本人比較喜歡低調路線,不過想想,既然都花了這麼多時間,這些影片要是沒有人看就太可惜了,因此來學一下農場的做法,希望大家覺得影片有你幫助的話,就幫小弟分享一下,無論是這篇文章或是上面 youtube 播放清單的連結都可以。

ps. 也能透過blog 旁邊的連結,用 Paypal 給點賞,鼓勵一下小弟,不過這不強求啦,畢竟 Paypal 手續費抽滿貴的。

2017年12月5日 星期二

不當行為

本書的全名是:<不當行為:行為經濟學之父教你更聰明的思考、理財、看世界>
本書的內容,是在說明作者從他研究所的研究開始,從開始單純收集資料,其後開始設計實驗發表研究,挑戰主流經濟學的觀點,最後創立行為經濟學這一個經濟學的分枝的整體回顧。

所謂的不當行為,其實是從當時主流的經濟學標準模型來看,標準模型將人類行為理想化之後,藉由簡化後的<人類>來對經濟做出預測,並在數十年間越發展越強勢,變成所有經濟學的現象都要依靠標準模型化的<人類>來解釋,任何偏離標準模型的研究,或者宣稱人類不符合標準模型的行為,在當時都會被視為異端邪說。
作者一路以來,就是不斷從人類的行為中尋找與標準模型不同的行為(也就是所謂的<不當行為>),試圖去推翻標準模型。

這裡可以舉一些很簡單的例子,例如標準模型可能假設,無論任何情境下,人對金錢是一視同仁的。
但有研究指出,我們對待同樣的 100 元,獲得 100 元跟損失 100元的快樂跟難過卻不是等價的,人們對損失會比獲得敏感,傾向規避損失。
又或者去便利超商買東西,如果店員告訴你,現在買的50元的商品在一個街口之外有5折的活動,你可能會為了這25元走一個街口;但如果你今天是買一台10000元的電視,一個街口外的賣場有 9950 的商品,你卻不會為了省這50元跑過去。對同樣的 50 元,我們在不同的情境下會有不同的價值,有時會想省有時不會--又是一個違反標準模型假設的行為。

當然如果只是把行為列出來是不會有什麼效果,畢竟人類如此複雜,標準模型也會推出它們對此類行為的解釋。為了推翻標準模型的假設,作者必須設計實驗,把實驗變數壓到最低,證實很難找到其他理由,讓標準模型能夠合理解釋這樣的行為,從而慢慢推翻標準模型中<人類的行為是完全理性、完全數字>的假設,書中對這些實驗的設計都有粗略的介紹。

要澄清的是,其實標準模型並沒有不好,人類行為跟思考太過複雜,沒經過適當的簡化,如果一開始就栽進複雜的世界,從一開始就會卡住完全做不出成果。
如果要我比喻,用我熟悉的電路來說,半導體的行為十分複雜,如果我們一開始就用完全真實的電晶體去做設計,光是最簡單的電路都做不出來,所以研究上會弄出截止區、飽和區的平方模型,幫助我們在大方向上可以近似電晶體的行為,才能有效的去設計複雜的電路。
但當模型被用過頭,假設所有電晶體都是理想的元件,許多真實電晶體的行為反而被忽略,而在設計上無法精準預測電路行為,這時就要打破舊有模型的框架,去創造新的模型才能更好的預測電路。
把平方模型/電晶體/電路代換成標準模型/人的行為/經濟活動,差不多就是這本書在談的事情。

在書中最後幾章,也有舉些例子說明,如何把行為經濟學的研究成果放在政府的政策下, 配合上面所說的,人類對損失比獲得更為敏感,讓我想到最近高雄市為了因應空汙推動大眾運輸,推出冬季搭乘大眾運輸免費的政策,這是一種獎賞或是<蘿蔔>的策略;如果要推大眾運輸,還有一種方式就是提高私人運具的成本,例如加強違停的拖吊,提高路邊停車的收費,這則是懲罰或是<棒子>的策略。
對照上面的人的行為,會知道用<棒子>政策可能會比<蘿蔔>有效很多,要把同樣人次趕向大眾運輸,騎機車被開單20元,可能在要大眾運輸上補貼40 元才有同樣效果,當然也是因為這樣,<棒子>的政策通常比較被大家討厭,造成政府常常在補貼政策上花大錢,成效卻不是很好,也許這是政策制定者值得參考人類行為研究的部分了。

若要說這本書有什麼缺點,我覺得這本書有點草率,全書的翻譯不是很好,漏字錯字有點多(我至少看到三個,沒看到應該會更多),注譯選擇在每章節結尾而不是出現的當下,書末也沒有附翻譯表跟專有名詞索引,讓人看得有點痛苦,原作有可能比譯作更完善一些。
我覺得以行為經驗學來說,這本書不算深入,但要說是導讀,說得有不夠全面能夠真正了解行為經濟學,如果沒有要完全看懂背後的經濟學原理,當小故事書看過去還算可以接受。整理來說不推,相關的議題,市面上應該會有更好的書才是。

最後是書名,其實後面那個「行為經濟學之父教你更聰明的思考、理財、看世界」根本是亂加的,真正的書名就是「不當行為:行為經濟學的形成史」而已,至於幹嘛加上思考、理財,我猜純粹為了吸引眼球吧,實際內容一點和理財一點關係也沒有。

2017年10月7日 星期六

論共享

其實這篇文章7月底就寫好了,只是一直都沒有寫完整貼出來,現在共享經濟已經慢慢進到衰退期,新聞也沒這麼多了,貼出來單純就是留個記錄XD

隨 obike 進駐台灣,讓台灣自 Uber, Airbnb 之後,再一次體會一個共享的商業模式,撇開 obike 違停造成的爭議不談,有一派的說法是,共享其實毫無新奇之處,飯店就是共享豪宅,圖書館是共享冷氣…等等。

我認為共享其實是個新概念,而不如上述所說,只是一個很潮的新名詞。

在過去其實是沒有共享,而是<公用>和<租用>的綜合,提供方是政府公家單位,亦或法人企業,就如上例中的圖書館、飯店,要服務大量使用者,清潔和維護都需要成本,因此會出現一個單一節點的單位為管理者。
與過去的公用及租用不同,現今的<共享>是運用科技,將管理的成本降到極低,同時允許一般民眾都能成為服務提供者,Uber, Airbnb 屬於此類,Uber 直接結合 GPS、刷卡付費、手機App 等科技工具,跳過管理計程車的規則,讓每個人都能成為計程車司機;Airbnb 則是允許任何有閒餘房子的人,上網登記提供給任何有短期需要的背包客。

兩者的重點都在於,透過網路大範圍的招募供應方和租用方,這和過去的公共提供,有單一節點的供應方截然不同。

就我這個定義來看,共享單車是否可稱為共享其實是存疑的,畢竟任何共享單車仍然有對應的管理單位,而非共享每個人擁有的腳踏車,我家裡有多的腳踏車,我並沒有辦法上網登錄,然後把它丟到路上讓大家使用,使用現行的腳踏車,一樣要向公司繳交押金、使用費用(對…其實就租金),這跟 Uber, Airbnb 所謂的共享,仍有一段差距。

目前共享在各地引起的爭議有兩種,第一如 Uber,在於直接挑戰各地政府對於出租車的規定;第二如共享單車,在於企業出租腳踏車大量佔有公眾資源(ex,違停佔用機車格、人行道),造成社會整體效能下降,引來政府管制。
共享單車的爭議其實不算太複雜,本來基於社會最大福祉,維護公有資源的使用量,政府就會對市場上的交易有所管制(我知道我寫最大福祉會有點爭議…不過我們姑且相信是這樣,才能討論下去),例如路邊停車格的設計,就是限制路邊(公共空間)的使用,以價制量,並對不守規矩的人拖吊,才不會變成馬路上都停滿車子;另外像是客運路線,政府也會介入,管制單一路線由哪些業者經營,以免熱門路線被大客車佔滿,偏遠路線卻無業者經營。

資源愈是珍稀,管制的範圍就會愈廣,由政府單一節點介入管制的機會也愈高;Obike 的爭議,充其量只是它把原先公眾免費的資源,使用到盡乎枯竭,引來政府介入罷了。

當然,這裡面牽扯的,又有更大程度的問題,像是政府規範的界限,政府究竟要無所不包還是儘量退縮?以 obike 的案例來看,這條界限是浮動的,取決於資源是否已經稀有到,需要政府介入分配,以免造成社會整體利益減損。
裡面牽扯的,包括我一直很好奇的,如日本的大手私鐵(ex. 阪急電鐵),它們在城市內建設地下化車站的時候,究竟是如何進行公眾相關的工作,例如土地取得、出口用地取得、交通維持等,這類具有稀有性和排他性的公眾資源使用。
我不認為一般的私人公司有這樣的權利進行這樣等級的資源分配,但若是由私鐵請求政府協助進行,豈不是政府直接圖利廠商?在市區內鐵道這種高度珍稀資源,難不成竟然是私鐵先搶先贏,建成之後完全排除了其他私鐵競爭的能力?想起來多少覺得有點怪怪的。

總之,針對共享經濟,我認為這是科技對社會又一衝擊,每每都在挑戰社會的接受度和容忍度,以及政府畫定管制界限的位置,除了完全禁止和完全開放之外,我們會需要更多的民眾討論,動態的進行實驗,我想是比較有效的解決方式。

2017年8月25日 星期五

使用rust closure實作fizzbuzz

之前用Rust 重寫Understanding Computation 裡面的ruby code,目前從 github 上來看,我的 Rust code 應該是僅次於原作者的 code,完成度最高的一個版本。
從去年五月,把大部分的 code 完成以來,唯一一個沒寫的章節:chapter 6 的 fizzbuzz,最近終於實作出來了\weee/。

本來我是用了比較直接的方法,也就是把closure 用function 來實作,使用generic 的方式來處理參數,例如在數字的部分,我們就要接受一個函式跟一個參數,這個函式要吃一個參數然後吐一個參數……。
例如我那時候實作的正整數的部分:
fn ZERO<F, T>(p: F, x: T) -> T where F: Fn(T) -> T { x }
fn ONE<F, T>(p: F, x: T) -> T where F: Fn(T) -> T { p(x) }
fn TWO<F, T>(p: F, x: T) -> T where F: Fn(T) -> T { p(p(x)) }
fn THREE<F, T>(p: F, x: T) -> T where F: Fn(T) -> T { p(p(p(x))) }
fn FIVE<F, T>(p: F, x: T) -> T where F: Fn(T) -> T { p(p(p(p(p(x))))) }

這個寫法的問題是啥?問題在於…我必須手動處理所有的型別,這在只有數字、布林的時候還容易處理,等到型別一複雜,這種函式宣告根本寫不出來,然後編譯器噴你一臉錯誤,最終完成的也只有number 跟 boolean,甚至連下一段的 is_zero 都實作不出來,程式碼我保留在 ch6-fizzbuzz 的分枝裡。

最近有天心血來潮,把我的 Rust code 實作成果貼到 rust forum:
https://users.rust-lang.org/t/computation-book-example-code-implemented-in-rust/12403
在討論串的下面有一位 jonh 回了我,他的辦法挺聰明的,實作的方式也比較符合這個 project 的要求,首先呢,我們不要處理這麼多型別的問題,把所有的型別都收到一個enum 之下:
pub enum Pol {
    C(Rc<Fn(Rp) -> Rp>),
    I(i32),
    B(bool),
}
pub type Rp = Rc<Pol>;
macro_rules! r {
    ($cl:expr) => {Rc::new(Pol::C(Rc::new($cl)))}
}

impl Pol {
    pub fn call(&self, x: Rp) -> Rp {
        match self {
            &Pol::C(ref c) => c(x),
            _ => panic!(),
        }
    }
}

型別 Rp 是用 rust 的 reference count pointer (Rc) 包裝這個 Pol 的型別,Pol::C 則是包裝一個 Rc 包裝的函式,該函式會吃一個Rp,吐一個Rp,等於是封裝了一個 lambda 函式。
另外我們利用自定義的 macro,讓產生這類封裝的 lambda 函式更容易,最後我們定義呼叫的 call 函式,它會把 Pol::C 裡的函式取出來,用 c 取用參數 x 執行。
這樣,就完成了函數的基本型態。
接著我們就能跟著這本書,一步步打造 fizzbuzz 的程式碼,例如上面提到的正整數的部分:
let zero  = r!(|_p| r!(|x| x));
let one   = r!(|p: Rp| r!(move |x| p.call(x)));
let two   = r!(|p: Rp| r!(move |x| p.call(p.call(x))));
let three = r!(|p: Rp| r!(move |x| p.call(p.call(p.call(x)))));
let five  = r!(|p: Rp| r!(move |x| p.call(p.call(p.call(p.call(p.call(x)))))));

這樣寫的問題是,我必須把所有的 closure 定義寫在 main 函式裡,因為 rust 不允許以 use 的方式,引入定義在別的檔案的 closure,以致最後 main.rs 高達 600 多行。
第二個問題是由於Rust 的所有權特性,在定義每個 closure 的時候,會需要不斷的 clone,例如 multiply 的 closure,需要用到 add 還有 zero,所以我們就要一路把 add 跟 zero clone 下去,寫到複雜一點的closure 例如 divide,需要使用 if, is_less_than, increment, subtract, zero,一個closure 的定義橫跨40 行,這寫法我覺得真的不行,不過一時之間真的找不到更好的寫法。
// multiply
// |m| { |n| { n(add(m))(zero) } }
let multiply = {
  let add = add.clone();
  let zero = zero.clone();
  r!(move |m: Rp| {
    let add = add.clone();
    let zero = zero.clone();
    r!(move |n: Rp| {
      n.call(add.call(m.clone())).call(zero.clone())
    })
  })
};
最後,我沒辦法把 Rp 這個函式印出來,像書裡面印出橫跨數頁,狀觀的lambda函式,這個問題也暫時無解。

最後的成果,完成的 fizzbuzz 所下所示:
let solution = {
  map.call(range.call(one.clone()).call(hundred.clone()))
   .call(r!(move |n:Rp| {
     _if.call(is_zero.call(module.call(n.clone()).call(fifteen.clone())))
        .call(fizzbuzz.clone())
        .call(
          _if.call(is_zero.call(module.call(n.clone()).call(three.clone())))
             .call(fizz.clone())
             .call(
               _if.call(is_zero.call(module.call(n.clone()).call(five.clone())))
                  .call(buzz.clone())
                  .call(to_digits.call(n.clone()))
             )
        )
   }))
};

執行起來慢的要死,fizzbuzz 1-100 費時 51s ,如果真的用 rust 寫,根本不用1 ms 好不好。
當然了,最終能用 rust 把這篇奇文給實作出來,還是覺得滿有趣的,中途也曾出現過,因為一個括號括錯地方,瞬間讓 multiply 變成 power 3*5 = 243,WTF!我至今還參不透,究竟為什麼括號括錯就會讓 multiply 瞬間升一級變 power OAO
我的程式碼都收到master branch 下面,可以參考 github連結,體會一下 functional programming 的奧妙之處XD
這篇文其實根本是「重新發明輪子的極致」,不止是演算法,我們要把整個整數系統、真偽值什麼的,都重新打造一遍,有一種我們先來種顆樹,長出來之後砍下來變木材,作成工具台之後開始打造輪子,感情我不是在寫 fizzbuzz,而是在玩 minecraft 呀(X。

2017年7月29日 星期六

設定 ssh讓人生簡單一些

ssh 是工作上的重要工具之一,平時要連進其他電腦、傳送檔案、甚至是上 ptt 都可以用 ssh 達成,這篇文整理一些 ssh 的設定,可以讓 ssh 的使用更簡單一些。

第一個是免打密碼的設定,這個如果有用 github 的話一定很清楚,簡單來說我們可以把電腦的公開金鑰放一份到遠端,登入的時候 ssh 就會不問密碼自動驗證。
步驟如下:
在家目錄下的 .ssh 目錄中,鍵入 ssh-keygen 指令,預設是使用 rsa,如果覺得 rsa 不夠安全可能會被心算解開(誤,可以用 -t dsa | ecdsa | ed25519 | rsa 選擇要用哪種公開金鑰加密法,用 -b 來選擇生成的金鑰長度(不過我下了 ssh-keygen -b 16384 然後它金鑰生不出來…)。
金鑰生成後,會詢問檔案要存在哪,預設就是 .ssh 資料夾;另外會問 pass phrase,我們都用上 public key 就是不想打密碼,除非有安全性考量否則留空即可。
Enter file in which to save the key (/home/garbage/.ssh/id_rsa): /tmp/id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
會產生兩個檔案,id_[algorithm] id_[algorithm].pub,從檔名看 pub 自然是公開金鑰了。
接著將 .pub 檔案的內容,複製到伺服器上 .ssh/authorized_keys 裡面,如此一來 ssh 就能免密碼登入了

詳細請參考
https://blog.gtwang.org/linux/linux-ssh-public-key-authentication/

第二個是設定 ssh config,這有點像 ssh 專用的 /etc/hosts,可以幫常連的機器設定別名,甚至是連線時要用什麼動作,以下來看看:
首先,假設我們要連線一台電腦,remotemachine.com 或者是 ip,帳號名稱是 yolo,開的 port 為 9453,要連線要打入這樣的指令:
ssh yolo@remotemachine.com -p 9453
當然如果照這篇文章安裝了 fzf ,某種程度上能大幅緩解連一台機器要打很多字的問題--連機器的指令不會變,用fzf 找出來就是了,但每次都用 fzf 來找還是會花一些時間,這時可以改用 ssh config
在家目錄的 ~/.ssh/config 檔案中,加上以下內容:
Host MyMachine
 HostName remotemachine.com
 User yolo
 Port 9453
ssh MyMachine 就會直接連上 yolo@remotemachine.com -p 9453
這些規則不是寫死的,ssh 的設定優先次序是命令列、.ssh/config、/etc/ssh/ssh_config,設定後照樣可以用 another@MyMachine 來使用其他使用者登入,或者用 -p 來改變連線的埠。
設定檔就是許多 Host 為開頭的區塊,內容為針對該 Host 的設定,上面展示的就是設定預設主機、使用者跟埠,還有許多其他設定可用,像是認證檔的位置、選擇加密方式,詳細可以看 man ssh_config

下面是我查到 ssh config 的契機,平常工作的地方開了一個新的工作室,但平常測試的主機A放在工作室A,兩個工作室的網段不一樣,沒辦法透過 ip 直接連線;為了連線所以在 router 上面鑽一個洞,開一個 ip 會直接進到工作室A的另一台主機B,到主機B就進到內網,可以直連測試主機A。
如果要打指令,大概會長得像下面這樣,等於是透過machineB ,開一個 pseudo-tty,再執行 ssh進到machineA:
ssh -t userB@machineB.ip -p 9453 ssh userA@machineA.ip
要簡單一點找到這個 stackoverflow,關鍵字是ssh proxy,在 .ssh/config 裡面加上這些設定
Host machineB
  Hostname machineB.ip
  User userB

Host machineA
  User userA
  ProxyCommand ssh -q machineB nc -q0 machineA.ip 22
ProxyCommand 指定要連到這台 Host 時要下的指令為何,這裡會用 ssh quiet mode ,再執行 netcat 接入machineA,這樣只要用 ssh machineA 就能完全上述工作啦
當然這樣每次連線都要打兩次密碼,不想打密碼,照上面在機器上放入自己的公鑰即可。
Related Posts Plugin for WordPress, Blogger...