TAMALOG

プログラミングがあれば遠いところへ行けます。プログラムと人の共生を記録します。

ブログツールを移行したい

アウトプットしたいなぁという思いがあるものの、アウトプットするプラットフォームどうしたらいいんだろ?と先に考えてしまって、今、ブログツールを移行したいという漠然とした思いを抱えている。

エンジニアらしく、GitHubでNetifyとHugoを使ってやる個人ブログ作成してもいいかなと思ったり、書くことに集中できるMediumもいいなと思ったりしてまだ決まっていない。

Elmにはまっている

ElmはTEAさえ分かってしまえば、シンプルにかける。

ただ、モデル設計に頭を使う。 `type` なのか `type alias ` なのか。まだ慣れていないので迷いがちだ。

 

副作用がTEAに任せられるのがとても気持ちいい。elm/coreのライブラリは必要最低限を備えているように思えるので、環境構築に戸惑いがちなフロントエンドはしばらくElmに任せようと思う。

WACATE2日目の感想

WACATE 2018 夏に参加しています。WACATE最終日が終わったので2日目の感想を書きます。

tamanobi.hatenablog.com

おいしいカレー

毎年恒例らしい。

きれいな景色

目的

単体テストだけでなく、より上流のテストについて学ぶために参加しました。

概要

以下の内容をやりました。テストケースを作成するワークがとても大変で、頭が疲れました。招待講演に関しては別の記事にまとめる予定

  • ワーク
  • ワーク振り返り
  • 招待講演「原因結果グラフとWACATEが僕に教えてくれたこと」

ワーク

ワークの内容自体は単純で、仕様書からテストケースを作りなさいというものです。

  • A4 1枚の仕様書(今回は稟議書承認システム)
    • 仕様書の曖昧な部分はチーム内で合意すること
  • 1チームあたり5人あるいは6人
  • 制限時間は2.5時間
  • ゴールは「テストケースを作ること」

僕のチームは、最終的にはテスト手順を9通り作りました。稟議書の状態遷移だけです。 本当は、アクティビティ図からのテストケースを1つでも起こしたかった。

感想

UMLの有用性がわかった

UMLがテストケースを作るためにここまで有用だと思いませんでした。でも、僕が使いこなすにはまだまだ時間がかかりそうです。 適切な粒度を見出さないとうまくモデリングできないから。人によって粒度がさまざまでした。僕はかなり細かくなってしまってモデルが複雑になることが多かったです。

プログラミングをする上で、この粒度は非常に細かくなります。でも、ブラックボックステストでは粒度は荒くなります。

UML(モデリング)は何のためか

システムをモデリングすると、さまざまな観点で議論しやすいと感じました。UMLには、ユースケース図、アクティビティ図、シーケンス図、ステートマシン図などありますが複数の図を使えば、その数分だけの観点で議論できます。

以上の点で、1日目の講義で、アクティビティ図、シーケンス図、ステートマシン図の3つを学べたことに強く感謝しています。

テストがうまいとは

「テストがうまいとは何か」という疑問をもって参加しましたが、ワークを介して仮説ができました。「システムを自在な粒度と観点でみられること」だろうと思っています。

ユーザーから見たらシステムがどうみえるか?稟議書の状態はどう変化するのか?システムと連動するときは?さまざまな粒度と観点で見ることがテストにおいて重要だと思います。

テストエンジニアリングとは

ワークや交流を通じて確信したことが2つあります。

  • テストは上流から入り込まないといけない
  • すべてのテストを網羅することはできない

テストは上流から

テストエンジニアリングとは、テストケースを単に作成するだけではなく、ときには仕様を決めたり、曖昧性を排除したり、テストしやすいような結合度を考えたり、ユーザーのことを考えて機能を決めたり、幅広い範囲だと思います。

すべてのテストを網羅することはできない

ワークの時間切れを体験して、テストケースをすべて網羅することはできないと確信しました。僕のチームは、ステートマシン図から0スイッチカバレッジが100%になるようにテストケースを作成しましたが、これが複数の状態変化をカバーする1スイッチカバレッジや2スイッチカバレッジを100%満たすようにケースを作成した場合、テストケースは膨大になります。

現実的に網羅できないのであれば、最もカバーしなければならない点を定めてケースを決定する必要があります。

コミュニケーション

テストエンジニアのみなさんは、人当たりがめちゃくちゃ良かったです。人との折衝が多いからでしょうか?あるいは、他人は自分とは異なる観点を持っていて自らの学びにつながる可能性を知っているからでしょうか?

こんなに暖かく素直なコミュニティは見たことがなかったです。

東京に来てから、「優しい振りをした損得重視のコミュニティ」しか見たことがなかった。それこそ、悪質なネットワークビジネスのような(ネットワークビジネスのすべてが悪いわけではありません)。

まとめ

  • テストコミュニティは、初心者に開けていて、明るくて、前向きで、おもしろおかしい
  • テストについて知らなくても、テストに興味があれば、ぜひWACATEに参加して欲しい
  • WACATE 2018夏は上流工程を知らない自分にとって、とんでもなく学びになった

余談

このWACATE 2018夏で知った手法を会社に持ち帰って、活かそうとするのは良い心意気だと思いました。 だけど、僕がこのWACATEで理解したのは、「何が問題か」「どこが重要か」見極めることです。

勇み足にならないために、ゆっくりと問題と向き合って、そのとき適切な手法で解決しよう。

WACATE1日目の感想

WACATE 2018 夏に参加しています。今は二日間の一日目。

wacate.jp

目的

単体テストだけでなく、より上流のテストについて学ぶために参加しました。

おいしいまぐろ丼

概要

今回のテーマはモデリングです。UMLユースケース図、アクティビティ図、状態遷移図について学びました。

大学時代にUMLを学びましたが、ソフトウェアテストの文脈で触れるのは初めてです。

モデリングの演習では以下が出題されました。個人ワークとチーム内共有をそれぞれやります。

一人でテストを設計すると、気づかないことが多いと実感しました。チームメイトが共有してくれるたびに、驚きの連続でした。

ECサイトのアクターにカスタマーサポートが出てきたり、注文者だけでなく非会員が出てきたり。いろんな観点があるなと。

久しぶりUMLを書いたので、全然時間が足りませんでした。特にUMLを書いたあとのテストケースの列挙が間に合っていません。この原因は明らかで、テストを前提にUMLを書けなかったことです。テストするために、どのような観点でモデリングするのか考えられていなかったと反省しています。

明日はチームで演習があるので、そのときにはテスト観点を忘れずに取り組もうと思います。

思わぬサプライズ

ワークが終わって入浴後、ディナーセッションで本をプレゼントしてもらいました。

https://twitter.com/tamanobi/status/1007956027478704129?s=21

ソフトウェア・テストの技法はまだ読んだことがなかったのでとても嬉しいです。

マイヤーズさんの書籍だったので、他の参加者と「マイヤーズの三角形」について盛り上がりました!

感想

テストエンジニアコミュニティは、人のつながりが強いと思っていましたが、たまたま仲が良いだけで初心者ウェルカムな雰囲気でした。これほど健全なコミュニティは見たことないです。打算が全く感じられない!

明日は、チーム一丸となって課題をガリガリ解くので今日の反省を踏まえつつ、望みたいと思います。まだ参加して1日目ですが参加してよかった……。

余談

ご飯はおいしかったし、タロット占いもしてもらえました!

カテゴリカルデータに対するロジスティック回帰分析

どんな手法でも性質を知らずに、使うことは避けたほうが良い。

ロジスティック回帰分析を調べていると、説明変数が連続ではない場合(カテゴリカルデータ)について知りたくなった。 試しに擬似データで、一通り分析をしてみる。

性別と年齢層が説明変数、クリックしたかどうかが目的変数のデータを用意した。ディスプレイ広告を想定している。 https://drive.google.com/file/d/1yqUND_5lih4cHqAr3QFjsjaJc7IFoLz4/view

全体のコード

playground/logistic_regression at master · tamanobi/playground · GitHub

必要なライブラリ

カテゴリカルデータを可視化する vcd が必要となる。

install.packages('vcd')

データ生成の方法

floor(runif(n = 10, min = 0, max = 2)) とすることで、0か1の数値を10個生成することができる(http://d.hatena.ne.jp/biochem_fan/20131116/1384586970)

データの偏らせ方

性別が男性(male)であること、年代が30代(30s)であることのいずれかのとき、クリックをしやすいように調整した。

具体的には、rbinomで試行を1回(size=1)、観測回数を1(n=1)を指定して確率だけ変更した。例えば、maleであるときに成功確率を0.7としている。

clickするかどうかは、click_rateが0.5を超えるかどうかで0,1を分けている。

コード

samplesize <- 1000
sex <- factor(floor(runif(n = samplesize, min = 0, max = 3)), labels = c("male", "female", "other"))
agegroup <- factor(floor(runif(n = samplesize, min = 0, max = 5)), labels = c("10s", "20s", "30s", "40s", "50s"))

a <- sapply(sex, function (x) {
  b <- 0
  if(x == 'male') b <- rbinom(n=1,size=1,prob = 0.7)
  else if (x == 'female') b <- rbinom(n=1,size=1,prob = 0.5)
  else b <- rbinom(n=1,size=1,prob = 0.1)
  return(b)
})

b <- sapply(agegroup, function (x) {
  c <- 0
  if (x == '30s') c <- rbinom(n=1,size=1,prob = 0.7)
  else c <- rbinom(n=1,size=1,prob = 0.5)
  return (c)
})

click_rate <- scale(x = (a+b), center=min(a+b), scale = (max(a+b) - min(a+b)))
click <- factor(ifelse(click_rate > 0.5, 1, 0), labels = c("n", "y"))
ad_click <- data.frame(click=click, sex=sex, agegroup)

記述統計量

生成された、ad_clickについてどのようになっているか観察する。clickは大きく偏っているが、sexやagegroupには一様に分布しているようだ。 f:id:tamanobi:20180609182311p:plain

集計表を用いたカテゴリカルデータの分布

集計表を作り、どこに偏りがあるか、各変数に相関はあるか確認する。

# visualization
crosstab <- xtabs(~ click + agegroup + sex, data=ad_click)
pairs(crosstab, lower_panel = pairs_assoc, shade=TRUE) # https://www.slideshare.net/KumarP34/using-r-for-customer-segmentation

f:id:tamanobi:20180609184332p:plain

左下三角成分は、各変数間のアソシエーショングラフである。lower_panel = pairs_assocを指定することで、左下三角成分をアソシエーショングラフ(assocで生成されるグラフ)に変更できる。 f:id:tamanobi:20180609185050p:plain

アソシエーショングラフ

clickとsexについてassoc を使ってグラフを描いた。上の図の3行1列のグラフに相当。 f:id:tamanobi:20180609191337p:plain

Rによるカテゴリカルデータの視覚化 によれば、グラフは以下を示しているらしい。

長方形の高さは残差、幅は期待度数の平方根、面積は観測度数と期待度数の差に比例する。各長方形はゼロをベースラインとし、残差が正の場合は場合はベースラインの上方、その逆であればベースラインの下方に配置する。

公式のDocmentも見ておいたほうがよさそうである(assoc function | R Documentation)。

このアソシエーショングラフからわかるのは、clickしたmaleの数が期待値よりも大きいこと、clickしなかったotherの数が期待値よりも小さいことである。性別に関しては、データの偏りがこのグラフだけなんとなくわかる。

playground/logistic_regression at master · tamanobi/playground · GitHub

ロジスティック回帰

Rでは以下のコマンドを使う。

ad_click.glm <- glm(formula = click ~ sex + agegroup, data = ad_click, family="binomial")
summary(ad_click.glm)
> summary(ad_click.glm)

Call:
glm(formula = click ~ sex + agegroup, family = "binomial", data = ad_click)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-1.1280  -0.8558  -0.4470  -0.3402   2.3993  

Coefficients:
            Estimate Std. Error z value Pr(>|z|)    
(Intercept) -1.36684    0.21408  -6.385 1.72e-10 ***
sexmale      0.69872    0.17350   4.027 5.65e-05 ***
sexother    -1.43706    0.24924  -5.766 8.13e-09 ***
agegroup20s  0.19564    0.25298   0.773   0.4393    
agegroup30s  0.55084    0.24969   2.206   0.0274 *  
agegroup40s -0.01657    0.26547  -0.062   0.9502    
agegroup50s  0.31678    0.26197   1.209   0.2266    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 1085.75  on 999  degrees of freedom
Residual deviance:  974.58  on 993  degrees of freedom
AIC: 988.58

Number of Fisher Scoring iterations: 5

sexmaleの項、sexotherの項、そしてagegroup30sの項がかなり強い影響を及ぼしていることがPr(>|z|)の列から見てとれる

Coefficientsの列が、推定された係数である。この係数をexp関数にかけるとオッズ比が求まる。

オッズ比

クリック確率をpとしたとき、クリックしない確率 1 - p の比をオッズ比という。

説明変数それぞれのオッズ比は、ロジスティック回帰によって推定された係数から導ける。

> exp(ad_click.glm$coefficients)
(Intercept)     sexmale    sexother agegroup20s agegroup30s agegroup40s agegroup50s 
  0.2549121   2.0111755   0.2376243   1.2160923   1.7347097   0.9835625   1.3726984 

各変数が1増加したときのオッズ比となる。すなわち、sexmaleがTrueになるとオッズ比が2倍になる。

説明

よりビジネスに近い形で説明する。

  • 男性(male)は、ほかの性別よりもクリック率が2.01倍になる
  • 男女以外(other)は、ほかの性別よりも、クリック率が0.23倍になる
  • 30代(30s)は、ほかの年代よりも、クリック率が1.73倍になる

以上のことから、 30代男性 に広告を多く配信するとクリック率向上が見込める。

カイ二乗分布を描いてみる

カイ二乗分布を知っていたつもりだが、正規分布から簡単に生成できることを忘れていた。

カイ二乗分布は、独立に標準正規分布に従うk個の確率変数の二乗和が従う分布。

実際に、標準正規分布から10000個ずつ出して分布を出してみた。k = 10 くらいになると形状が正規分布に近くなる。

f:id:tamanobi:20180605013136p:plain

コード