Lean Baseball

No Engineering, No Baseball.

BPStudyとわたしの5年 - 技術・野球でキャリアの出世魚になるまで #bpstudy

f:id:shinyorke:20190310162102j:plain

※写真はこちらから引用しました(Baseball Play Study 2017冬より)

先に断っておくと、純然たる野球ネタではなく、単なるふりかえりです.

春の到来と共に、ついにこちらのシーズンがやってまいりました⚾*1

bpstudy.connpass.com

18人(+主催の@haru860さんの始球式)のLT*2、今から楽しみです.

ちなみにですが、昨年引退宣言した私も18人の一人として6回裏に1イニング登板します(何を話すか&引退撤回の理由は後半にて).

気がつけば、2014年のBaseball Play Study初回は登壇者3名、参加者はなんとたった19人!と小さく始まったのですが、次回は登壇者は18人、参加者は(おそらく今回も)100名超えするまで大きくなったBaseball Play Studyおよび、本来の母体(であるはず)のBPStudyに参加者・登壇者として関与してはや5年経ったので、今後のことも含めてふりかえりたいと思います.

結局言いたいことは

自分の専門性(技術・野球)を言語化し、発表・アウトプットした結果、望んだキャリアを「自己実現」できたのがBPStudyにおける最大の学び

  • レベル云々関係なく、発表は大事
  • 発表とフィードバックにより、「専門性」と「技術者としての人格」が磨かれる
  • 今後もBPStudyで技術・野球関係なく、「専門性」と「技術者としての人格」を磨くと共に、同じような「機会」を提供できる自分でありたい

BPStudyとわたしの5年

おさらい - BPStudy #とは

いわゆる「IT系勉強会」のイベントの一つで、私の解釈としては、

何かしらの技術者(と技術者に絡むなにかの人たち)が自身のノウハウ・知見を発表し、参加者・主催者双方が撮れ高を得る月に一度の勉強会

です.

なお、公式ページには以下のように説明されています(原文そのまま引用)

BPStudyは、2007年9月から毎月1回のペースで開催しているWeb系勉強会です。(「 ○○Study」と名前がついている勉強会の元祖です。)

技術者(デザイナーの方が発表したこともあります)が、自分のノウハウや知見を発表する 「技術者のTED」 のような勉強会を目指しています。

発表者は、発表をきっかけに自分の専門性を再確認する。周囲には専門性を認知され、キャリアを築いていく。聴衆側は、発表を聞いて知識を得たり、議論したりして刺激を受ける。

そのようにBPStudyに参加することで、自分の中の何かが変わり、何かやってみようと思い、その小さな行動がきっかけで未来が創られていく。

そのような場になればよいとおもいます。

重要なポイントとしては、野球専門のイベントではない!そういうことやぞ.*3

ちなみに、私とBPStudyの馴れ初めは2013年のこの会で、主催の@haru860さんとの初対面および、野球の話で盛り上がりすぎて栄えある初回Baseball Play Studyの登壇を勧められました*4.

Baseball Play Studyの歴史(駆け足)

自分の発表についてのふりかえりはここでしません(すでに済んでるので).

Topixとして面白いな&個人的な思い出をピックアップします.

2014年(初回)

最初の方に書いたとおり、初回は佐藤さん、当時からいろんな活動で著名なエンジニアであるござ先輩、そして(少なくとも今よりは)当時無名だった私の3名で発表しました.

bpstudy.connpass.com

三人のLTのあと、順位予想や展望を会場の19人みんなで語りつつ、そのまま流れで飲みに行ったのはホント最高でした.

個人的にはこの半年後(2014年9月)に長年勤めたコンサル企業を退職してリクルートに移籍したのですが、

地味にこの時の発表(BPStudyに登壇は凄い!的な)がいくつかある決め手の一つになりました(実話)*5

2015年(この年から年二回に)

この年から、現在定番となっている年二回(3月・12月)に.

春の回は基調講演として現役ライターの方が登壇、そして現行のスタメン登壇者がちらほらと.

bpstudy.connpass.com

個人的なエピソードとしては、この回で「ギータの三冠王・トリプルスリーなんぞ夢のまた夢やぞ!」と煽る→このシーズン見事トリプルスリー達成

...の結果、参加者の@a_macbee氏(ちゅらデータ(株)代表、元PyLadies Tokyoオーガナイザー)に後日見事にマサカリLTを決められた.

amacbee.hatenablog.com

参加者にちなんだ思い出だと、共通の友人からせきさん*6を紹介してもらった、同じ野球・グルメ好きでエンジニア思想も近いクールな友人と出会えたのもBaseball Play Studyの撮れ高でした.

「春だけじゃ足りない!シーズンオフもやろうぜ!!」という圧が各方面から?上がり、この年から12月のBaseball Play Studyスタート.

bpstudy.connpass.com

なんと、面白いことに歴史と伝統あるBPStudy全体での100回目!

@dankichiさんの「信号機」トークで思いっきり腹筋壊れるまで笑った記憶が.

f:id:shinyorke:20190310180544j:plain
この表現はずるいでしょ笑(佐々木さんスライドより)

続きはぜひスライドの方を読んでもらえると.

www.slideshare.net

野球に限らず、分析ってやっぱシチュエーション大切だなと妙に学んだのと、これぐらいインパクトあることやりたい!と改めて思いました.

2016年(最所さんデビュー)

春先も息を吸う用に登壇、この年は自分で作ったライブラリを用いた統計分析を披露.

bpstudy.connpass.com

なお、その後この発表の内容はその後紆余曲折を経て、前年にマサカリLTをした@a_macbee氏とPyCon JP 2016共同発表というオチにつながる*7.

参加者30人ちょっと、この頃まではまだ内輪感もそれなりにあった感.

が、この年のトピックスはやはり、年末の回における、IT野球女子界の絶対的エースである最所あさみさん(@qzqrnl)のデビューかなと.

bpstudy.connpass.com

SNS運用を絡めたマーケティングと野球愛を絡めたLTはホント見事だった.

www.slideshare.net

この年あたりから、

野球でLTするなら「四象限図」最強やぞ!

という、「フライボール革命」的なモノが発生する.

というわけで、登壇する人、四象限オススメやぞ!*8

2017年(野球エンジニア誕生前夜)

春はこちら.

bpstudy.connpass.com

参加人数60人オーバー!!!過去最高動員を達成する.

また、会場も広くなった.

@7pairsさんのテキストマイニング・ネタもだいぶ定番化、ここはホントに観戦ポイントの一つ.

www.slideshare.net

そして冬は野球エンジニアになる前最後の発表、「年俸」というベタかつセンシティブなテーマで攻めた.*9

bpstudy.connpass.com

前述の「四象限テクニック」で一発長打を決めたのですが、結局の所これに持っていかれる.

流石、絶対的エースの最所さん.

なお、今回で引退らしいので必見やぞ.

2018年(ついに参加者100人超え)

トピックスはやはり、私の引退...じゃなくて、ついに参加者が100人超えたこと.

bpstudy.connpass.com

ちなみに、過去の回にデータスタジアムさんやライターさんなど、何人か「ホンモノの人」も出ていたのですが、この回は弊社ネクストベースから森本さんが登場.

そして前回はこちら.

bpstudy.connpass.com

一気に登壇者が増える「エクスパンション」が発生.

この回は仕事⚾の出張(ウィンター・ミーティング)の為不在でしたが、遠くラスベガスからTL眺めながら「Baseball Geeks賞」の選考ということで、論理参加してました.

BPStudy(野球じゃない方)について

野球関係は、前回の2018冬を除き、フル出場・すべて登壇.

その他の会も時間とタイミング次第で参加したり登壇したりしました.

はじめてのLean Canvas〜最初のアイディアを言語化してみよう(2015)

野球だけじゃなく、技術者としても振り幅・やれることを増やしたいという思いがあり、「リーンスタートアップの話で登壇したい!」と言った結果、機会をいただきました.

bpstudy.connpass.com

リーンキャンバスの書き方ワークショップをその場でやりました.*10

www.slideshare.net

今でも私のバイブルな、「実践リーンスタートアップ」を元にオリジナルのコンテンツを提供してワークショップしました.

Running Lean ―実践リーンスタートアップ (THE LEAN SERIES)

Running Lean ―実践リーンスタートアップ (THE LEAN SERIES)

  • 作者: アッシュ・マウリャ,渡辺千賀,エリック・リース,角征典
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2012/12/21
  • メディア: 単行本(ソフトカバー)
  • 購入: 3人 クリック: 14回
  • この商品を含むブログ (19件) を見る

当時、仕事や勉強会でワークショップに参加することはあっても、「自分でファシリをする」という経験をしたことがなかったので非常に良い経験になったと記憶しています.*11

今の仕事や、コミュニティ(#rettypyほか)で生きてるファシリ力の始まりはここだったかも.

エンジニアとしてのスタメンを掴むまで(2018)

これは去年の話.

bpstudy.connpass.com

詳細はここで振り返っているとおり、「BPStudyで創り上げた自分のキャリア話」です.

shinyorke.hatenablog.com

デブサミ2018および、GeekOutで言及した内容をBPStudyの参加層に合わせてブラッシュアップして話をしました.

自己実現の参考になれば!という思いで、「ぜひこの話をさせてください!(枠が空いたら)」と佐藤さんにお願いして実現しました.

これからの関わり方(Baseballもそうじゃない方も)

今後もBPStudyには参加者・(機会をつくって)登壇者としてコミットしていきます.

Baseball Play Study復帰からの引退撤回

どの面下げて帰ってきたんですか!?ということで、一年で復帰を決めました.

bpstudy.connpass.com

復帰の理由ですが、

  • 試していた野球統計のアプローチ(仕事ではない)がいい感じにできた
  • この成果、せっかくだから発表したいなあー→せや!Baseball Play Studyや!!
  • 前回(2018冬)、新顔メンバーの発表は裾野が広がって、嬉しかったものの、正直「ココロオドル」ような発表が無かった*12

「ココロオドル」発表無いからワイが手本見せたろかい!!!

ってことで引退を撤回しました.

なお、いくつかの勉強会・もくもく会でトレーニングに入っており、先日こちらのイベントでも素振りをしてきました.

kawasaki.rb #069 を開催しました #kwskrb

野球エンジニアとして、セイバーメトリクス勢として頑張りたいと思いますので当日ぜひご期待くださいませ!

なぜ発表を続けるか

野球が好きだから、、、というのもありますが

  • レベル云々関係なく、発表は大事
  • 発表とフィードバックにより、「専門性」と「人格」が磨かれる

この二つが主たる理由です.

レベル云々関係なく、発表は大事

2014年、無名時代から今に至るまで、はじめての事も自信あること・経験あること両方発表してきて、いい経験もしくじった経験もたくさんしました.

しくじった時は手厳しいフィードバックもちょいちょいいただきましたが、

  • IT系の勉強会は「発表することそのもの」が称賛される
  • いい勉強会はネガティブなフィードバックでも「次に繋がる」ような感じでオススメしてくれる

BPStudyはまさにそのような場所のお手本で、私個人の今後のキャリアでもありえる「様々な挑戦」に対する壁打ちもしくはふりかえりの場としてアウトプット出せたらと思っています.

なお、今年はまだ野球以外のネタが無いので思いついたらやりたいなと.

発表とフィードバックにより、「専門性」と「人格」が磨かれる

発表者は、発表をきっかけに自分の専門性を再確認する。周囲には専門性を認知され、キャリアを築いていく。聴衆側は、発表を聞いて知識を得たり、議論したりして刺激を受ける。

「公式ページ」の説明より引用

技術そのものやプロセス、特定ドメイン(広告、法律、野球、将棋etc...)といった「専門性」を「認知」され、「キャリアを築いていく」という点でホントそのとおりかなと思います.

事実、私もリクルートへのJOINそして今のキャリアにつながる「出世魚」になれたのもBPStudyのおかげという点もあります.

さらにもう一つ、磨かれた点としては「技術者としての人格」もあるかなと思っています.

  • 怠惰であること、論理的であることetc...いわゆる「プログラマブルな思想・思考」
  • 他の技術者や技術者以外の人とも交わり、議論したり共創したりするような「ダイバーシティ」的な心
  • 倫理観(法を守る、弱者・未経験者への配慮etc...)

他にももっとあるかもしれません.

BPStudyだけでもないのですが、「良いコミュニティ」でこれらを学び、自然と磨かれた気がします.

自分もまだまだな点もありますが、今後もこれらを磨き学べたらと思います.

機会をつくる・伴走する(BPStudyをパクって)

とはいえ、自分もそれなりのキャリア・ポジションなので、「参加する」だけでなく、「機会をつくる・伴走する」事も合わせてやれたらと思います.

主催しているPythonのもくもく会(#rettypy)なんかもそうですが、

今のエンジニア文化の広がり・ムーブメントに単にのっかる!ではなくて、必要な「専門性」「技術者としての人格・振る舞い」といったところも、合わせて広がってもらいたいと思っています.

この辺、 #rettypy 以外のアクションはモヤっとしていますが、自分のペースで無理なくなにかやれたらと思います.

何はともあれ、3/27(水)のBaseball Play Study 2019楽しみましょう!!!

*1:オープン戦ちょいちょい見てます、土曜日の侍ジャパンは色んな意味で変な声出ました(震え)

*2:レギュラーに新顔加え、昨年登板した弊社トップアナリストの森本が再び登場します、そちらもよろしく!

*3:ハッシュタグが一緒だからね、しょうがないね

*4:ここに至る背景として、佐藤さんと共通の友人であり、リーンスタートアップ・アジャイルの勉強会で友となっていた「高さ危険太郎」さんこと、@ken_takasakiさんが事前に佐藤さんに野球のことなどを吹き込んでいた事により、話が円滑に進みました.高崎さんありがとう(今更)

*5:だからと言って、BPStudyで野球の話したらリクルートに入れる、というモノではないです、そんなに甘くないよリクルート

*6:グノシーでデータ分析している人.私は頻繁に連絡取る友人が少ないほうですが、なんやかんやで彼とは結構やりとりしてます.

*7:PyCon JPにおける野球発表5回における唯一の共同発表に.この件は楽しかった.

*8:四象限テクは野球を抜きにしてもよく使ってます、というかリクルートで学んだんだけど野球での応用のキッカケは最所さんかも

*9:このタイミングじゃないとできないだろ!っていう思いもあり.この一ヶ月後にRetty退職およびネクストベースへのJOINを発表.

*10:当時凝ってたかつ、仕事でも使ってた内容で今でもちょいちょい使ってます.

*11:人と関わってモノゴトを進める、「手取り足取り教える」ではなく、「入り口を手伝って”自走”してもらう」を意識して経験できたのはよかった.

*12:具体的には、「ファンとして好きなんだなあ」「心意気は伝わるなあ」と思ったものの、「技術」「専門性」という所で躍るモノが無かった.「野球エンジニアやりたい!」志望の方もいると聞いてますが流石に厳しいなと.

CTOになる前・なった後に学んだこと - 「エンジニアのためのマネジメントキャリアパス」を読んで

f:id:shinyorke:20190211162241j:plain

去年からメチャクチャ気になってた「エンジニアのためのマネジメントキャリアパス」、読みました&あっという間に読了しました.*1

エンジニアのためのマネジメントキャリアパス ―テックリードからCTOまでマネジメントスキル向上ガイド

エンジニアのためのマネジメントキャリアパス ―テックリードからCTOまでマネジメントスキル向上ガイド

  • 作者: Camille Fournier,及川卓也(まえがき),武舎広幸,武舎るみ
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2018/09/26
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログ (1件) を見る

エンジニア組織のマネジメントをはじめて正味2年ちょい、CTO歴(やっと)1年の自分としては、

CTO・エンジニアリングマネージャーになる前に読んでおきたかった!!!ってぐらいの名著でした!!!

っていうくらい素晴らしい書籍でした、自信を持ってオススメできます.

このエントリーでは、

この三本立てで感想なりポエムなりしたいと思います.

TL;DR

  • テックリードやマネジメントへのキャリアを考えてる方もそうじゃない方も、「エンジニアのためのマネジメントキャリアパス」一度は読んでおけ
  • ゼロからはじめるエンジニア組織作りは、エンジニアとしてもビジネスマンとしても視座・視野が広がり、仕事を通じて色々と学べる
  • テックリード、エンジニアリングマネージャー、CTO(VPE)目指すなら小さいところからはじめるのオススメ&最後は技術に頼るトコ多いやぞ!

スタメン

私のエンジニア・マネジメントなキャリア

昨年のデブサミでもちょっと触れていますが、改めて棚卸し.

  • 2018年〜今:ネクストベースのCTO.フルタイムのエンジニアは2人(自分込み)、他に学生インターン1人、ちなみに経営陣ではありません*2
  • 2017年1月〜9月:Rettyでテックリード→エンジニアリングマネージャー
  • 2016年(半年程度):ビザスクでインターンのメンターやったり小規模プロジェクトのリードしたり
  • 2014年(三ヶ月ぐらい):SUUMO(リクルート)のとある事業のエンジニアリード
  • 2012年ごろ(これも半年):ベイカレント・コンサルティングのとある顧客チームのエンジニア・リード

途中メンバーに戻ったり色々と紆余曲折ありましたが今は何とかかんとか小さいチームながらもCTOやってる人、そう見てもらえればと思います.*3

「エンジニアのためのマネジメントキャリアパス」の感想

感想をザックリ書くと

技術系管理者のキャリアパスを大局的な見地に立って紹介している本。キャリアの各段階に即したきわめて戦術的な助言や提言が得られる。技術系の管理者は部下に対して、優れた管理術を身につける責任を負っている。本書で管理のノウハウを学んで欲しい。技術系管理者の職責を詳細に紹介、解説している実用的な手引書である。

エンジニアのためのマネジメントキャリアパス」 推薦の声より.

全くもって「推薦の声」どおり、ホントにそのとおりの本でした.

そして私の感想は、

  • 今までテックリードやエンジニアリングマネージャーをやってきた数々の失敗について大いに反省した
  • 何故失敗したか?どうすれば同じ失敗をしないか??、のヒントと指針をたくさん頂いた
  • CTO #とは という、エンジニアの数だけ考え・意見を持っているこの件に対する自分なりの「CTO道」が見えた&登る気になる元気をもらった

このエントリーを書くため、もう一度はじめの章あたりを読んでいるのですが、くしくも及川卓也さんの「まえがき」と同じことを言ってる気がします.

これから本書を読もうとする読者の方々にこんなことを言うのはふさわしくないかもしれないですが、本書を読み終わった後、私はひどく落ち込んでいる自分に気づきました。それは、本書の内容に不満があったり、不快に感じた部分があったということではまったくなく、むしろ逆にその内容が素晴らしい故に、いかに自分が未熟であったかを思い知らされたからでした。

エンジニアのためのマネジメントキャリアパス」 まえがき、から抜粋.

この本を手にとったマネージャーの方々(私含む)、きっと同じ感想なんだろうなと思います(真顔).

目次と概要

章ごとに何が書いてるかという簡単な解説を.

個人的には、

自分がどのフェーズにいようが、最初から最後まで読むとストーリーを十分追えるのでかなりオススメです!*4

推薦の声・まえがき・はじめに

読む前のイメージを掴む意味でもしっかり読んだほうがいいトコでした.

いやこれはホントすごい*5.

1章 マネジメントの基本

名前の通り、「そもそもマネジメントってなんぞや?」という話.

1on1やフィードバック、トレーニングって、、、というところを触れています.

個人的にはこの辺も合わせ読むと理解深まると思いました.

ヤフーの1on1―――部下を成長させるコミュニケーションの技法

ヤフーの1on1―――部下を成長させるコミュニケーションの技法

実際、1on1本読んでたおかげでこの辺はスッキリと内容が入りました*6.

2章 メンタリング

名前の通り、新人や新規加入メンバーに対するメンタリングについての章.

個人的には今まで複数社で学生さんや新人のメンターをしてきたので、その経験と合わせ、色々と思い出しながら読みました.

3章 テックリード

開発チームの責任者たる、「テックリード」に関する章.

  • 職務時間の3割程度、チームと共にコードを書きつつ
  • 開発チームに対する責任を担う、開発リーダー

たる方々に対する章です.

なお、この本で(特に心に傷負うことなく)スラスラ読めるのはこの辺までかなと思います(真顔)*7

4章 人の管理

こっから心の傷に塩をすり込むような内容が増えてきます(震え)

いわゆる、「部下を持った管理職」に対する助言・考え方が中心です.

自分は読みながらこの辺にブクマしてました.

「継続的なフィードバック」の文化をチームに根付かせる

勤務評価など、「管理職として何かしらのアクションを起こす」前にちゃんと「継続的にメンバーを見てフィードバックしてますか?」と説いててなるほど!と思いました.

  • 部下の基本情報を仕入れる
  • 日頃から部下を見守る習慣を
  • 深刻な話題も日常レベルのフィードバックで「さらり」と

それぞれ何書いてるかは実際に本を手にとって読んでほしいのですが、私からすると色んな思い出が走馬灯のように蘇る内容でした(真顔)

5章 チームの管理

一つのチームに対する課題・問題解決の章.

本の表現としては、

機能不全に陥ったチームの「デバッグ」の基本

というド直球な表現で記載されています.

いろいろと書いてあって学びも深かったのですが、私は特に、

誰しも人に好かれたいのはやまやまだが、管理者は「優しさ」よりも「親切」を旨とすべし

この言葉が一番刺さりました.

6章 複数チームの管理

複数のチームを束ねる職責、「技術部長」「開発部長」みたいな肩書を持ったときの心得など.

この章に書いてること、今の所無縁かなあ?と思いつつも、ここが刺さりました.

部長職を引き受ける前にたっぷり時間をかけてコードを書く作業を十分経験し、最低でも1種類のプログラミング言語を自在に使いこなせるようになっていないと、コード書きの作業からすっかり「足を洗ってしまう」ことの危険ははるかに大きくなります。

私は幸いにも(言うても2名+1名チームなので)バリバリコードは書いてる、Pythonであれば手足のように自在に操れる*8のでこの危険には面してないのですが、

「こいつイケてないなあ」っていうエンジニアリング・マネージャーや部長はこの傾向思いっきり当てはまるのでは?と思い震えました.

7章 複数の管理者の管理

複数チーム管理に加え、「管理者を管理する」という、「ヴァイス・プレジデント見習い」みたいな職責についたらどうしますか?の話.

  • 道を踏み違えてる新任管理者を何とかする
  • ベテラン管理者(会社のカルチャーに合ってない)をどうにかする

...中々震える話が多い印象でした(震え)

その他、技術投資(いわゆるR&Dとか)もこの辺で触れています.

8章 経営幹部

「あなたは経営陣のひとりです!」的なポジションについたら、の章.

こっからいよいよCTO的な内容です.

技術戦略や優先順位、やりにくい仕事(例:レイオフを伝える)をどうする?などに触れています.

9章 文化の構築

会社の文化・思想をどうやってポリシー作ったり、職務・給与レンジに合わせた組織作り(キャリアラダー)どうする?的な章.

横断的なチーム作りや、意外なところでは「コードレビューを通じた文化作り」などにも触れています.

10章 まとめ

まとめというか励ましというか...w

エンジニアリングなマネージャー業ふりかえり

...とまあ、色々と感想を書きましたが、自分の実務体験上どうだったか?のふりかえりをします.

「傾聴」の大切さ

メンバー相手の1on1、インターンくんや新人くんとの会話、経営陣とタイマンをはるetc...

結局何をするにしても、「傾聴」って重要だな!っていう学びがありました.

1on1でのアドバイスがうまく行ったときも、「予算くれ!」と交渉するときも、

  • 相手の立場や仕事だけじゃなく、人柄も把握する
  • 話を聞く、と同時に自分もオープンになる
  • 事によって、モノゴトが少しずつでも前に進む

これらがうまく行くと結果が出ましし、逆に結果に結びついてない時はどれかが欠けてるなあ〜、という印象があります.

「プロセス」の使い所(なんでもアジャイルにすんな)

「process czar(プロセスツァー)になるな!」そういうことです.

エンジニアのためのマネジメントキャリアパス」の3章で、かなりいいことが書いてました.

プロセスツァーの「対極」に位置するのは、「プロセスを完全に排除する管理者」ではありません。そうではなく、「プロセスは、チームのニーズや、チームが進めている作業のニーズを満たさなければならないという点を深く理解している管理者」です。

皮肉なことに、アジャイルは多くの場合、(「機敏な」「素早い」といった本来の意味とは正反対とも思える)「厳格な」方法論に基づいて実装されます。*9

私自身、アジャイルの信奉者ですが、エンジニアリング・マネージャーしたりCTOしながらこれに薄々気がつく→徐々にやり方を変えたことによってよかったことがあった(≒変える前はいくつもの失敗を重ねていた*10)なーっと学びました.

これはCTOになる前はちゃんと言語化出来てなかったのですが、知らない間に行動に移せたので良かったのかなと思っています.

なお、昨年のこちらのエントリーにそのまま直結する話であるとも思っています.

shinyorke.hatenablog.com

「技術アピール」からはじめる人脈つくり

カンファレンスでの発表、もくもく会の主催そしてこのブログを通じて今の仕事にたどり着いた、のもありますが、「この人はリードたる技術とかあるよね」的な信頼を外堀から埋める意味でやっててよかったと思っています.

何かのイベントをするときに登壇してくれたり会場提供してくれたりという支援をもらったり、逆に自分も支援して信頼貯金を稼げたりといい事づくしだったと思います.

っていう話はこの辺にもあるのでご興味ある方はぜひどうぞ.*11

note.mu

ゼロからのチーム作り(まさに今)

これはCTOとして現在進行系のことなのですが、今まで培ってきた人脈やつながり、採用スキルを生かして「世界最強の野球エンジニア・チーム作り」をゼロからやれているのは良いことかと思っています.

11月に一人フルタイムでJOIN、今後ももっと人増やせるように頑張ってる最中(詳細は言えませんが)ですが、ここまでに至る所で今までの経験が生きていて、

「ちょっと遠回りしたエンジニア人生だったけどよかったのでは?*12

と思っています.

テックリード、エンジニアリングマネージャー、CTOを目指す方へ

最近たまにこういう相談受ける&だいたい、いつも同じ回答な気がするのでまとめて書こうかなと.

CTO1年生を終えて2年生の自分が言うのも恐縮ですが、

  • 創業期もしくは資金調達後の1人目エンジニアからはじめようぜ!
  • 「目標とするエンジニア」「憧れのCTO」像を明確に持って自分を鍛える

この二つをオススメします.

創業期もしくは資金調達後の1人目エンジニアからはじめようぜ!

実を言うと、エンジニアのためのマネジメントキャリアパス」に書いてあること、まんまです.

望む望まない関係なく、色んな経験が降ってきますし、途中の採用や、「ブリリアントジャーク*13」対策など、嫌というほど味わえます.

「このチームで働きたい!」っていう所にあったらスッと挑戦すべきです.

なお、大企業出身者の人だと「部課長になってから動けばなれるのでは?」「声かかるまで待つ」的な人もたまに見受けられますが、

  • 確実にアテになる人脈あるならそれでも構わない、時期見て入っちゃおう
  • 人脈が無い(アテがない)場合、何かしらの外部アウトプット・活動が無いとそもそも検索にヒットしない(SEOみたいなもの)

という現実と向き合った上で判断したほうがいいかなと思います.*14

「目標とするエンジニア」「憧れのCTO」像を明確に持つ

これは本に書いてない事です.

CTOになる前・なった後両方共、

「あの人(スーパーなエンジニア)だったらどういう判断・決断するかな?」

という想像と、自分が下した判断・決断のDiffを取る事により、自分の技術・ビジネススキルや判断力・決断力を磨くようにしてました.

その対象がCTOやVPEだったりすると、Diffを取ってる内に自然とCTOやVPEに必要なスキル・判断力・決断力が身につくと思うので、ぜひやってみては!?

以上、今年はじめての書評でしたー

*1:出たのは昨年ですが、昨年は意図的にこの手の本を避けていたので今年に入ってから読み始めましたとさ.

*2:が、エンジニアリングに対する責任は自分が持っていること、決断・判断に必要な権限は有しているのでCTOと名乗っても問題ないと思っています.

*3:出入りが激しいのは転職が多いからってのとやっぱ寄り道と言うか紆余曲折が

*4:私はAction Reading好きで結構飛ばしながら読む派なのですが、この本に関してはそれは該当しないと思い、時間かけて最初から最後まで読みました.

*5:まえがきでここまで読み応えがある本も珍しい.

*6:1on1の是非そのものは別として、Yahooのこの本は名著です、結構好きだし参考にしました.

*7:ここまでは割と大体の人が経験するハズ、何らかの形で.

*8:今までは野球のことがしたくてずっと分析・解析コードを書いてましたが、今は休みの日はちょっとした作業や写経を通じてコード書くようにして腕が腐らないようにしています

*9:厳しいことを言うと、アジャイルコーチやスクラムマスターで結果でない・イマイチな人はこれに気がついてないもしくは気がついてるけど無視してる、のどちらかだと思う.

*10:失敗は成功の母とはよく言うもんだなと、いやホント学んだし当時の関係者には申し訳ないというお気持ち

*11:我ながらよくまとまってると思う

*12:今年でキャリア19年目、40歳でマネージャー業が正味2年ちょい、残り17年は思いっきり回り道してたよ!って意味

*13:意味は本読んで欲しい、実際この対策色々と経験してちょっと強くなった感ある

*14:これも厳しいこと言うと気が付かない人は「大企業病」に罹患してるよきっと

うわっ…私のpandas、遅すぎ…?って時にやるべきこと(先人の知恵より)

f:id:shinyorke:20190120111403j:plain
※あくまでもイメージです(適当)

仕事じゃなくて、趣味の方の野球統計モデルで詰まった時にやったメモ的なやつです.*1

一言で言うと、

約19万レコード(110MBちょい)のCSVの統計処理を70秒から4秒に縮めました.

# 最初のコード
$ time python run_expectancy.py events-2018.csv
       RUNS_ROI
outs          0     1     2
runner
0_000      0.49  0.26  0.10
1_001      1.43  1.00  0.35
2_010      1.13  0.68  0.32
3_011      1.94  1.36  0.57
4_100      0.87  0.53  0.22
5_101      1.79  1.21  0.50
6_110      1.42  0.93  0.44
7_111      2.35  1.47  0.77
python run_expectancy.py events-2018.csv  72.93s user 3.75s system 99% cpu 1:16.83 total

# 完成形
$ time python run_expectancy.py events-2018.csv
       RUNS_ROI
outs          0     1     2
runner
0_000      0.49  0.26  0.10
1_001      1.43  1.00  0.35
2_010      1.13  0.68  0.32
3_011      1.94  1.36  0.57
4_100      0.87  0.53  0.22
5_101      1.79  1.21  0.50
6_110      1.42  0.93  0.44
7_111      2.35  1.47  0.77
python run_expectancy.py events-2018.csv  3.68s user 0.64s system 100% cpu 4.291 total

学びの整理、自分への戒めとしてちょっとだけメモを公開します.

TL;DR

  • Dataframe処理からfor文を戦力外通告し、データを絞って処理したら70秒掛かってた処理が6秒になりました(小並)
  • df.iterrows()が許されるのは写経&実験コードぐらい.ちゃんとmapを使おう(applyは要審議),データは必要な分だけ読み取りましょう
  • テストを書こう,先人たちの知恵に感謝しよう

おしながき

やったこと

PyCon JP 2017の発表でやった、LWTSのうち、「得点期待値(Run Expectancy)*2」を以下の書籍を参考に算出コードをPythonで書きました(申し訳ないですがコードは非公開*3).

Analyzing Baseball Data with R, Second Edition (Chapman & Hall/CRC The R Series)

Analyzing Baseball Data with R, Second Edition (Chapman & Hall/CRC The R Series)

原著はタイトルの通り、Rで書かれている*4ので、

  • ひとまずRで写経する(JupyterでRカーネル動かして写経)
  • 途中計算の答え合わせをしながらPythonで書き直し、この時にpandasで実装
  • テスト(Pythonのunittest)を書いて動かし、ひたすらリファクタリング

というスタイルでやりました.

なお、対象データはメジャーリーグ1シーズン分の打撃スタッツ(公開データです*5)で、約19万レコード,100カラムくらいのCSVファイル(110MBちょい)というちょっと手ごわいデータです.

$ ls -lh events-2018.csv
-rw-r--r--@ 1 hoge fuga  113M 11 25 13:58 events-2018.csv

処理と出力の結果はこんな感じです.

$ python run_expectancy.py events-2018.csv
       RUNS_ROI
outs          0     1     2
runner
0_000      0.49  0.26  0.10
1_001      1.43  1.00  0.35
2_010      1.13  0.68  0.32
3_011      1.94  1.36  0.57
4_100      0.87  0.53  0.22
5_101      1.79  1.21  0.50
6_110      1.42  0.93  0.44
7_111      2.35  1.47  0.77

コードは見せられませんが、雰囲気(Interfaceと処理の役割)だけ伝えるとこのような感じです.

import csv

import pandas as pd


class RunExpectancy:

    def __init__(self):
        pass

    def calc_csv(self, filename: str) -> pd.DataFrame:
        # 何かしらの処理
        return self.calc_df(pd.read_csv(filename))

    def calc_df(self, df: pd.DataFrame) -> pd.DataFrame:
        """
        Calc Run Expectancy for Dataframe
        :param df: Pandas Dataframe(Retrosheet Events Data)
        :return: Pandas Dataframe
        """
        df['A'] = df['B'] + df['C']
        # ひたすら前処理と集計

        # 複数カラムにまたがる処理を愚直にforでやってるところ(イメージ)
        for i, row in df.iterrows():
            status = 0
            if row.D == 'chiba' or row.E == 'chiba':
                status = 33
            elif row.D == 'nishinomiya' or row.E == 'nishinomiya':
                status = 4

            df.at[i, 'NHK'] = status
        # ↑のようなforで回すやつが2箇所


        # いよいよ算出&出力
        return self._output(df)

    @classmethod
    def _output(cls, df: pd.DataFrame) -> pd.DataFrame:
        """
        Export Run Expectancy Data
        :param df: Pandas Dataframe(RUNS ROI Data)
        :return: Pandas Dataframe
        """
        # ひたすら整形するそして算出
        # ピボットしてRun Expectancyを出す
        return pd.pivot_table(df, index='runner', columns='outs')


if __name__ == '__main__':
    import sys

    run_ex = RunExpectancy()
    values = run_ex.calc_csv(sys.argv[1])
    print(values)

70秒を4秒に縮めた際にやったこと(ふたつ)

もういきなり結論書いちゃいますが、

  • df.iterrows(forでグリングリン回ってるところ)を戦力外通告してmapに置き換え
  • 計算に必要なカラムを定義、pd.read_csvのパラメータで「usecols」をカラムを指定(読み込むデータを限定)

これで一気に時間が縮まりました.

df.iterrowsを戦力外通告してmapを使う

pandasのDataframeに新しいSeries(カラム)を作りたい!でも複数のSeriesから計算しなくちゃ...!

っていう時に、人は(私は)どうしてもforで回すことを考えがちです.

def calc_df(self, df: pd.DataFrame) -> pd.DataFrame:

    # 中略
    # 複数カラムにまたがる処理を愚直にforでやってるところ(イメージ)
    for i, row in df.iterrows():
        status = 0
        if row.D == 'chiba' or row.E == 'chiba':
            status = 33
        elif row.D == 'nishinomiya' or row.E == 'nishinomiya':
            status = 4
        df.at[i, 'NHK'] = status

for文書いたら負けかなと思っている」という有名な格言?もあるとおり、19万レコードを全部forで舐め回しているこのコードは負けのコードです.*6

人のコードを写経してまず動かす!って時はいいのですが、たかだか100MBちょいのCSVの計算集計に70秒もかかるのはって思いはじめた段階で、真面目に考え、mapで処理を書き直しました.

mapで書き直す

上記の例をmap(Seriesの値から計算)するように書き換えるとこんな感じです.

def _nhk(self, status_text: str) -> int:
    # デリミタ(_)で分ける
    params = status_text.split('_')
    status = 0
    if params[0] == 'chiba' or params[1] == 'chiba':
        status = 33
    elif params[0] == 'nishinomiya' or params[1] == 'nishinomiya':
        status = 4
    return status

def calc_df(self, df: pd.DataFrame) -> pd.DataFrame:

    # 中略
    df['STATUS_TEXT'] = df['D'].astype(str) + '_' + df['E'].astype(str)   # 中間列を作ってデリミタでつなぐ
    df['NHK'] = df['STATUS_TEXT'].map(self._nhk)

STATUS_TEXTという名前で中間列を作り、これをmap関数内で分解(str split)して処理するようにしました.

applyはさほど速くない

なお、pandasにはDataframe(≒複数のSeries)を元に処理するapplyという関数もあり、上記のイケてないfor文コードをこういう書き方にもできます.

def _nhk2(self, row: pd.Series) -> int:
    status = 0
    if row.D == 'chiba' or row.E == 'chiba':
        status = 33
    elif row.D == 'nishinomiya' or row.E == 'nishinomiya':
        status = 4
    return status

def calc_df(self, df: pd.DataFrame) -> pd.DataFrame:

    # 中略
    df['NHK'] = df.apply(self._nhk2, axis=1)

コードの可読性・綺麗さ(かっこよさ)でいうと圧倒的にapplyを使ったほうがお得*7なのですが、残念ながらこのコードのパフォーマンスは、forを使うときよりだいぶ良かったのですが、mapよりダメな子でした.

なんでやろうな?と思い調べたらpandasでお馴染みsinhrksさん*8のブログに解説がありました.

sinhrks.hatenablog.com

pandas.DataFrame は列ごとに異なる型を持つことができる。DataFrame は内部的に 同じ型の列をまとめて np.ndarray として保持している。列ごとに連続したデータを持つことになるため、そもそも行に対するループには向かない。また、DataFrame.iterrows でのループの際には 異なる型を持つ列の値を Series として取り出すため、そのインスタンス化にも時間がかかる。

また 行ごと / 列ごとに 関数を適用するメソッドに DataFrame.apply があるが、このメソッドでは Python の関数を繰り返し呼び出すためのコストがかかる。apply は利便性を重視したメソッドのため、パフォーマンスを気にする場合は避けたほうがよい。

※「1. 行に対するループ / DataFrame.apply は 使わない」より引用

forで回すのはアレだよ!、for文は負けだよ!っていう件も含めて明確な答え、ありました.

for文を戦力外通告した結果(70s->20s)

最初に書いたコードはなんとforで回したところが二箇所、19万レコードのDataframeを二回も回すという恐ろしいことをしていました(反省).

33-4どころの負けじゃありません.*9

これらをひたすらリファクタリングし、もう一度計測した結果、

$ time run_expectancy.py events-2018.csv
       RUNS_ROI
outs          0     1     2
runner
0_000      0.49  0.26  0.10
1_001      1.43  1.00  0.35
2_010      1.13  0.68  0.32
3_011      1.94  1.36  0.57
4_100      0.87  0.53  0.22
5_101      1.79  1.21  0.50
6_110      1.42  0.93  0.44
7_111      2.35  1.47  0.77
python run_expectancy.py events-2018.csv  15.58s user 3.40s system 100% cpu 18.950 total

70秒が約20秒、7割ちかく処理時間をカットしました(震え).

そもそものデータを減らす

とはいえ20秒もまだかかり過ぎだな...と思い、データを見直した所、

  • CSVは100カラムちょいある
  • しかし、使ってるカラムは10個も無い
  • 必要なものだけ読めばよいのでは?(震え)

って事に気が付きました.

いつもは何も考えずに無邪気にread_csvしてDataframe作ってましたが、これを絞ることにしました.

カラム指定する(read_csv)

もう一度ソースコードと計算式を読み直し、必要なカラムのみ特定し、read_csvを書き直しました.

# 書き直す前
#    def calc_csv(self, filename: str) -> pd.DataFrame:
#        return self.calc_df(pd.read_csv(filename))

# 書き直したやつ
    COLUMNS = ('A', 'B', 'C', 'D', 'E') 
    def calc_csv(self, filename: str) -> pd.DataFrame:
        # 書き直した後
        return self.calc_df(pd.read_csv(filename, usecols=self.COLUMNS))

個人的にはread_sqlからやるときは明確に必要なカラムのみ指定(select文をちゃんと書けば出来る)して意識してやってたのですが、csvの時はあまり考えずにやってたので、「もしや!?」と思い調べてやってみました.

read_csvをいい感じにした結果(20s->4s)

参考にさせてもらったこちらのブログのベンチマークでも明確に結果が出ていたので期待してベンチをとりました.

starpentagon.net

$ time python run_expectancy.py events-2018.csv
       RUNS_ROI
outs          0     1     2
runner
0_000      0.49  0.26  0.10
1_001      1.43  1.00  0.35
2_010      1.13  0.68  0.32
3_011      1.94  1.36  0.57
4_100      0.87  0.53  0.22
5_101      1.79  1.21  0.50
6_110      1.42  0.93  0.44
7_111      2.35  1.47  0.77
python run_expectancy.py events-2018.csv  3.68s user 0.64s system 100% cpu 4.291 total

見事、処理時間が1/4近く短縮されました!

「うわ...私のpandas、遅すぎ...?」という懸念が見事に解消されました、めでたしめでたし.

なお、ここまでの高速化は調べながらリファクタリングとテストを繰り返して半日で達成しました.*10

高速化をちゃんとやる前に

テストを書きましょう!!!リファクタリングしましょう!!!データを把握しましょう!!!!

ホント、これに尽きます.

テストを書いてからリファクタリング

何故テストが重要か?という話はこちらの名著に譲るとして*11

テスト駆動Python

テスト駆動Python

この手のデータ分析のリファクタリングでありがちな失敗は

リファクタリングしてる内に、オリジナルのコードから正解がズレる(=コードを壊してしまう)

ことです.

手法やモデルが決まってるということは当然再現性あるはずなのに、リファクタリングの結果再現しなくなったらそれはバグです(やってることの意味がなくなる).

ある程度完成してprintやlogで書き出していい感じになったら、

  • インテグレーション(結合)レベルでいいのでテストを書く、ちゃんと書く
  • ややこしい処理や計算をしている関数は個別にユニット(単体)レベルで書く
  • 書いたテストを常に動かす仕組みを用意する(エディタの設定なりCIなり)

pytestとかじゃなくて、標準のunittestでも十分なクオリティを出せるので、早い段階で用意することをおすすめします.

import unittest

class TestRunExpectancy(unittest.TestCase):

    # テストデータはpy-retrosheetから別途ダウンロード

    def test_2016(self):
        """
        2016年データでのLWTS
        """
        run_ex = RunExpectancy()
        df = run_ex.calc_csv('./data/events-2016.csv')
        dict_run_ex = df.to_dict()

        # 0アウト
        dict_0_outs = dict_run_ex[('RUNS_ROI', '0')]
        self.assertEqual(dict_0_outs['0_000'], 0.5)     # ランナー無し

    def test_2017(self):
        # 省略

    def test_2018(self):
        # 省略

なお、個人的にはテスト駆動開発がしっくりこない*12為、必要と判断したとき以外はやってません(これは好みの問題).

必要なデータを認識する(でかいデータにビビらない)

統計モデルや計算手法をちゃんと確認して必要なデータだけに絞る.

この辺雑にやってついつい手を抜きがちですが、最初のコードを書いて動いた時点で吟味しても良かったのかな?と思っています.

最初の全体像がイマイチ不明でも、後ほどコードをgrepするとかで絞れると思う(今回はその方式でカラムを吸い出して決めました)ので、これは手を抜かずやっていきたい.

先人たちの知恵に感謝

mapやapplyの具体例などは定番のJupyter本を参考にしつつ.

PythonユーザのためのJupyter[実践]入門

PythonユーザのためのJupyter[実践]入門

今回はpandasのコントリビューターのsinhrksさんはじめ、有志のブログやドキュメントが大変参考になりました.

sinhrks.hatenablog.com

starpentagon.net

例を示した以外、私のこのエントリーでは新しいネタ・Tipsはほぼ無いわけですが、こういう知恵を少しでも残せる・継承できるようになれたらいいなあと改めて思いました.

以上、今年初の技術エントリーでした.

*1:もはやどっちだか見境つかない感あるが今回は間違いなく趣味

*2:LWTSはプレーを評価する方法の概念的な考えで、具体的な手法として得点期待値や得点価値があります.詳しくはウィキペディアもしくは私の過去発表を御覧ください(野球のエントリーではないのでここでは解説しません)

*3:趣味とはいえ、野球のコードを気軽にOSSにするのはちょっとですね(震え)なお、過去公開のコードやライブラリはそのままです&必要に応じてメンテをするお気持ちはあります.

*4:このRのやつに色々と苦労しましたがこれはどこかで書き残したい

*5:RETROSHEETという、公開データセットです.なお使い方には多少クセがあります(このブログのどこかに解説あったような) https://www.retrosheet.org/

*6:このブログは昨日個人的にやってたもくもく会で書き始めたのですが、ちょうど著者のはむかず氏からこのコメントが出たので引用させてもらいましたw

*7:この辺は明確すぎますね笑

*8:pandasで困ったらsinhrksさんですよねと、ホントいつも参考にしています

*9:NHK.

*10:これが2019年、私のプログラミング書き初めでした(仕事始めの前の日にリハビリでやった)

*11:元の本が素晴らしいのと、アジャイル・テスト駆動・Pythonのプロ、やっとむさん監訳で非常に安心と信頼ができる名著です

*12:テスト駆動開発、悪くはないんだけど、動くものがそこそこできてからテストを書き始める方がやりやすいと思っている