経験は何よりも饒舌

10年後に真価を発揮するかもしれないブログ 

Scrapboxを使って技術書を真剣に読む


23卒のエンジニア職志望向けAdvent Calendar Advent Calendar 2021の13日目です。

学生時代の行動指針としてインフラに長期間触れてみたいという思いがあり、いろいろ本を読んだりして準備していたのですが、いざインフラに常に触れられる状態になると、読んだ内容を詳細に思い出せないことに気がつきました。
自分の強みである、既存のコードを読む力はアプリケーションを開発するときにもインフラを構築するときにも役立っていますが、概念の習得、例えばアプリケーションでいうとDOMとは、インフラでいうとDNSとは、とかいう部分は長期間触れ続けないと忘れる、自分の場合は特にインフラの概念を忘れる傾向にあります。しかもそれは既存のコードを読む力の前提となる部分であるから、確固とした知識を入れておかないといけないと感じました。
技術書は一回読むだけではなく繰り返し読むことが多いですが、早く読み終わりたいという意識が無意識に働き、重要な概念を読み飛ばしていることが早期の忘却につながっているのではないかという仮説を立て、今一度じっくり技術書を真剣に読みなおすという方針を立てました。
そこで用いたのがScrapboxで、まずは『ネットワークはなぜつながるのか』の重要な部分を書き起こしながら読むことと、登場した概念をリンクにすることを実践しています。

今のところかなり効果を感じています。
読んだ内容を脳内で整理してからまとめて書くことにより理解が深まるし、後で追いやすいです。また、読み流して無理矢理前に進むことがなくなりました(1周目に関しては読み流してでも本の全体像を把握することは有用だと思うが、2周目、3周目で読み流すのは避けたい)。
学部時代に独学で習得すべきジャンルは既に全て一回は読み流しているはずなので、これからはじっくりまとめながら確固とした知識を吸収し続けたいです。

統計検定1級受験記

統計検定1級の「統計数理」と「統計応用(社会科学)」を受験したのでいろいろまとめておく。

モチベーションと数学力

モチベーションとしてはいくつかあって、まずは時間があった。
夏の終わりから11月にかけてアルバイトを控えていたので、今までしてこなかった資格勉強をしようという気になった。
勉強したい資格として、統計検定、データベーススペシャリストネットワークスペシャリスト、TOIEC、簿記2級、AWS認定資格があった。
ネットワークスペシャリスト、簿記2級に関しては受ける時期がまだ先だったので手をつけなかった。
TOIECに関しては一回受けたことがあるしいつでも受けられるので手をつけなかった。
AWS認定資格は学習期間にも費用がかかり続けると思ったのでモチベーションが湧かなかった。
データベーススペシャリストはちょうど秋にあったので10月に受けてきた(結果が出たらまとめる)。

そもそもなぜ統計検定を受けたかったかというと、まずは数学をきちんと勉強したかった。
ソフトウェアエンジニアとしてアルバイトやインターンをする上では数学力不足に悩んだことはなかったが、趣味でHaskellを深めるためにTaPLを手に取ったり、社会科学と因果分析に興味をもったり、OSSのもっとコアな部分を理解しようとした時に数学の壁があった。
社会学部で、そこそこちゃんとした統計の講義やゼミを受けたり、般教で線形代数を取ったことはあるけれど、あくまで文系生徒を対象としたもので、一般の理系学部生がどれほどの理解力を求められているのかを知るためにも統計検定は有用だと思った。
あとは機械学習がアプリケーションに組み込まれることがスタンダードになってきているように見えていて、機械学習分野の動向を全く無視して過ごすのも自分の中ではうーむという感じがしおり、まずは数学への圧倒的理解力不足を解消したかった。
記述式の対策をした方が数学を解く練習になりそうだからと、統計応用の社会科学に興味があったからという理由で1級を選んだ。

今まで数学を全くしてこなかったわけではなかった。
数学1と数学2は高校生の時に学んでいたし記憶もあったので、青チャートを眺めてこんな感じだったと思い出せる状態ではあった。
今年に入ってからゼロから作るDeepLearningを読み始めたり数学3の教科書をSymPyで解き始めたりしていた。
なんとなく高校数学を思い出したり、数学3をカバーしたり、線形代数をちょろっと理解している状態ではあったが、数学の問題を解くという練習や行為は受験以来全くしてこなかったので、本格的に対策をすることにした。

対策

まずはネットで情報を集めた。
統計検定 1 級に合格する方法 - Qiita
文系で統計検定1級に合格した|khosoda|note
統計検定1級の勉強法|蒼天|note
統計検定一級受検体験記-ぐぐりらにっき
|統計検定:Japan Statistical Society Certificate

情報を踏まえて参考書をいろいろ検討して、まずはマセマで基礎を固めることにした。
マセマの学習フローチャートでは確率統計に入る前に、微分積分があったからまず微分積分をすることにした。
また、他の記事では線形代数の知識もあったほうがいいと書いてあったので線形代数もすることにした。
9月から資格勉強をする時間がまとめて取れて、10月中盤にデータベーススペシャリストがあったから、10月中盤までに微分積分線形代数の基礎を固めることにした。
マセマは解説が非常に丁寧で理解しやすかった。
多少詰まるところはあったけど気にせず曖昧なままで最後まで進めた。
数学の問題を解くという行為に慣れるため、演習問題の解答を隠して紙に書いて解いてみるということもした。

データベーススペシャリストが終わったので残り1ヶ月で統計をどんどん進めることにした。
まずはマセマの確率統計を同じように多少詰まるところはあったけど気にせず曖昧なままで最後まで進めた。
これで微分積分線形代数、確率統計の大体の概要は把握できたから、マセマの次の本を検討した。

他の記事を参考にして現代数理統計学の基礎現代数理統計学のどっちかにしようと決め、京阪三条あたりの丸善でパラパラと眺めて自分に合っていそうな現代数理統計学の方を選んだ。
実際読み進めてみると、文章が多めで丁寧だということは伝わるが、各章の初めの方しか理解できず、各章の後半あたりは読み流すだけになってしまった。
理解度がかなり浅かったので、マセマと現代数理統計学の間を埋めるため、明快演習 数理統計を購入した。
各項目に例題がついているので、現代数理統計学で理解できなかった項目が例題の中で登場する場合は、使い方とか解き方がわかったりしてよかった。
ただマセマと比べたら解説が理解しにくく、繰り返し解くということはせずにリファレンスとして目を通して雰囲気を理解するために使った。
明快演習 数理統計でも理解できなかった現代数理統計学の項目は、はじめての統計学というYouTubeチャンネルの解説を紙にまとめて理解しようとした。
マセマの理解度に比べて明快演習 数理統計と現代数理統計学の理解度は格段に低かったが、とりあえず過去問に目を通してみることにした。
有意に無意味な話というサイトから2015/2018/2019の統計数理の過去問を3問ずつ取ってきて、2016/2017の公式問題集を購入した。
まずは2015/2018/2019の統計数理の過去問を解いてみたが、各問の小問1すら解けず、小問3もしくは小問4以降からは解説を読んでもわからないという状態だった。
関連する項目を現代数理統計学で深めようとしても、そもそも現代数理統計学もあまり理解できていないからほんの少し理解が進むだけだった。
とりあえず小問1,2に手をつけられるようにするため、マセマの説明文や解法を0から導出できる練習をした。
具体的には、演習問題をすらすら解けるようにする他、例えば「正規分布の確率関数からモーメント母関数を導出し、それを用いて正規分布の期待値と分散を求めよ。」というようにマセマの解説途中の説明文も自分で問題化してスラスラ解けるように練習した。
ある程度暗記が必要だったから4~5周くらいしてやっと何も見ずに解けるようになった。
2016/2017の過去問も解いてみて、統計数理に関してはだいたい小問1,2に手をつけられる状態、小問3以降は解説を読んでも理解が曖昧という状態になった。
統計応用に関しては人文・社会科学の統計学に一通り目を通して2016/2017の過去問を解いてみて、同様にだいたい小問1,2に手をつけられる状態、小問3以降は解説を読んでも理解が曖昧という状態になった。

ちなみに統計検定の申し込みは同志社大学でやった。
確か文化情報学部は無料になってその他の学部は少し割引が効いた。
申し込みのために半年ぶりくらいに今出川キャンパスに足を運んだ。
販売機の押すボタンを間違えてしまって初めて金融課にお世話になった。

本番

申し込みの時に会場を指定できたかは覚えておらず、会場はまあまあ遠い御堂筋ホールだった。
最寄りから1時間程度でOsakaMetro御堂筋線なんば駅に到着して駅内徒歩1分のビルで受けた。
会場はかなり広くて1テーブルに1人でゆとりのある状態で受けれた。

解いた感触は過去問を解いた時と一緒で、だいたい小問1,2に手をつけれて、小問3以降は手が出せなかった。
モーメント母関数を導出するのはそのまま出たので、マセマの解説途中の説明文まで解けるようにする対策は良かったと思う。

反省、抱負

受ける前からまあ受からんだろうなとは思っていたし、合格点に届く分量の解答を書いていないから受からないことは確定している。
対策時間がもっと長かったらという反省もないというか、対策時間をもっと長くとれば小問3以降とか現代数理統計学の理解が進んで合格に近づいたとかは思えなくて、対策時間という次元じゃなくて年単位の精進ではないかと思っている。
とりあえず統計に関してはgaccoなどの機会や他の参考書をあたってみたりして理解を進めていこうと思う。
1級はもう受けないけど準1級は学生の割引が効く間に取っておきたいから多分受ける。
数学を本格的に勉強する機会を設けれたことはかなり良かったと思う。
次は英語とアルゴリズムやっていくぞー。

Jestのカバレッジ計測について(モック編)

Jestのカバレッジ計測について - 経験は何よりも饒舌 で、「JestはJestのAPIを用いたテストに対してカバレッジを計測しているのではなく、テストで呼び出されたか否かでカバレッジを計測している」ことが分かったけど一応モックの場合も調査してみる。
モック自体は Jest のモック関数を整理する - 経験は何よりも饒舌 で整理している。

次のコードで調査していく。

const obj = {
  random: function () {
    return Math.random();
  },
  randomPlusOne: function () {
    return Math.random() + 1;
  },
};

module.exports = obj;

まずはモックを使わずにテストしてみる。

const obj = require("./sample");

describe("sample", () => {
  it("random", () => {
    expect(obj.random()).toBe(1);
  });
  it("randomPlusOne", () => {
    expect(obj.randomPlusOne()).toBe(2);
  })
})

予想通りテストは通らないが、カバレッジは100%になる。

$ npm run test

> jest-playground@1.0.0 test
> jest --collectCoverage

 FAIL  ./sample.test.js
  sample
    ✕ random (4 ms)
    ✕ randomPlusOne (1 ms)

  ● sample › random

    expect(received).toBe(expected) // Object.is equality

    Expected: 1
    Received: 0.0018626031125137388

       6 | describe("sample", () => {
       7 |   it("random", () => {
    >  8 |     expect(obj.random()).toBe(1);
         |                          ^
       9 |   });
      10 |   it("randomPlusOne", () => {
      11 |     expect(obj.randomPlusOne()).toBe(2);

      at Object.<anonymous> (sample.test.js:8:26)

  ● sample › randomPlusOne

    expect(received).toBe(expected) // Object.is equality

    Expected: 2
    Received: 1.732370688737492

       9 |   });
      10 |   it("randomPlusOne", () => {
    > 11 |     expect(obj.randomPlusOne()).toBe(2);
         |                                 ^
      12 |   })
      13 | })
      14 |

      at Object.<anonymous> (sample.test.js:11:33)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |     100 |      100 |     100 |     100 |                   
 sample.js |     100 |      100 |     100 |     100 |                   
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 failed, 1 total
Tests:       2 failed, 2 total
Snapshots:   0 total
Time:        0.537 s, estimated 1 s

ここで、一旦モックから離れて、ロジックに全く関与していない次のようなテストを試してみる。

describe("sample", () => {
  it("1+1", () => {
    expect(1 + 1).toBe(2);
  });
})

予想通り、カバレッジは0%になる。

$ npm run test

> jest-playground@1.0.0 test
> jest --collectCoverage

 PASS  ./sample.test.js
  sample
    ✓ 1+1 (2 ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |       0 |        0 |       0 |       0 |                   
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.526 s, estimated 1 s
Ran all test suites.

次に、前回のテストにrequireだけしたテストを試してみる。

const obj = require("./sample");

describe("sample", () => {
  it("1+1", () => {
    expect(1 + 1).toBe(2);
  });
})

すると、ロジックに全く関与していないのにrequireしただけでカバレッジは上昇している

$ npm run test

> jest-playground@1.0.0 test
> jest --collectCoverage

 PASS  ./sample.test.js
  sample
    ✓ 1+1 (2 ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |      50 |      100 |       0 |      50 |                   
 sample.js |      50 |      100 |       0 |      50 | 3-6               
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.433 s, estimated 1 s
Ran all test suites.

次はモックを実装して試してみる。

const obj = require("./sample");
jest.spyOn(obj, 'random').mockImplementation(() => 1);
jest.spyOn(obj, 'randomPlusOne').mockImplementation(() => 2);

describe("sample", () => {
  it("random", () => {
    expect(obj.random()).toBe(1);
  });
  it("randomPlusOne", () => {
    expect(obj.randomPlusOne()).toBe(2);
  })
})

カバレッジの結果は前回と同じであり、つまり、モックはカバレッジに関与していないことがわかる。

$ npm run test

> jest-playground@1.0.0 test
> jest --collectCoverage

 PASS  ./sample.test.js
  sample
    ✓ random (2 ms)
    ✓ randomPlusOne (1 ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |      50 |      100 |       0 |      50 |                   
 sample.js |      50 |      100 |       0 |      50 | 3-6               
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.571 s, estimated 1 s
Ran all test suites.

次のように、JestのモックではなくSinon.JSを用いてテストしてみる。

const obj = require("./sample");
const sinon = require("sinon");

const randomStub = sinon.stub(obj, "random");
randomStub.returns(1);
const randomPlusOneStub = sinon.stub(obj, "randomPlusOne");
randomPlusOneStub.returns(2);

describe("sample", () => {
  it("random", () => {
    expect(obj.random()).toBe(1);
  });
  it("randomPlusOne", () => {
    expect(obj.randomPlusOne()).toBe(2);
  });
});

カバレッジの結果は前回と同じであり、つまり、モックの方法もテストに関与していないことがわかる。

$ npm run test

> jest-playground@1.0.0 test
> jest --collectCoverage

 PASS  ./sample.test.js
  sample
    ✓ random (2 ms)
    ✓ randomPlusOne

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |      50 |      100 |       0 |      50 |                   
 sample.js |      50 |      100 |       0 |      50 | 3-6               
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.635 s

まとめ

  • モックの実装やモックの方法はカバレッジに関与していない

Jestのカバレッジ計測について

Jestのカバレッジ計測について、次のコードで調べてみる。

function sum(a, b) {
  return a + b;
}

function minus(a, b) {
  return a - b
}

module.exports = {
  sum: sum,
  minus: minus
}

sumだけテストしてみる。

const { sum } = require('./sample');

describe('sample', () => {
  it('sum', () => {
    expect(sum(1, 2)).toBe(3);
  })
});

結果は、Funcsが50%、Linesが66.66%になっている。
Funcssumminusのうちsumしかテストしていないので1/2で50%、行数は66%程度なんだな、と納得できる。

$ npm run test

> jest-playground@1.0.0 test
> jest --collectCoverage

 PASS  ./sample.test.js
  sample
    ✓ sum (2 ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |   66.66 |      100 |      50 |   66.66 |                   
 sample.js |   66.66 |      100 |      50 |   66.66 | 6                 
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.506 s, estimated 1 s

次のようなテストを書けば、予想通りカバレッジは100%になる。

const { sum, minus } = require('./sample');

describe('sample', () => {
  it('sum', () => {
    expect(sum(1, 2)).toBe(3);
  })
  it('minus', () => {
    expect(minus(2, 1)).toBe(1);
  })
});
$ npm run test

> jest-playground@1.0.0 test
> jest --collectCoverage

 PASS  ./sample.test.js
  sample
    ✓ sum (1 ms)
    ✓ minus

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |     100 |      100 |     100 |     100 |                   
 sample.js |     100 |      100 |     100 |     100 |                   
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.642 s, estimated 1 s

次に、やむを得ない状況が発生して一方でNode.jsのassert module、一方でJestのExpectを使用している場合を想定する。

const assert = require("assert")
const { sum, minus } = require('./sample');

describe('sample', () => {
  it('sum', () => {
    expect(sum(1, 2)).toBe(3);
  })
  assert.equal(minus(2, 1), 1);
});

カバレッジを出してみると、予想に反して100%になる。
てっきりJestのExpectを使用していないと計測できない(50%になる)と思っていた。

$ npm run test

> jest-playground@1.0.0 test
> jest --collectCoverage

 PASS  ./sample.test.js
  sample
    ✓ sum (1 ms)
    ✓ minus

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |     100 |      100 |     100 |     100 |                   
 sample.js |     100 |      100 |     100 |     100 |                   
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.642 s, estimated 1 s

つまり、次のようにテストをせずただ意味もなく呼び出しただけでもカバレッジは100%になる

describe('sample', () => {
  it('sum', () => {
    expect(sum(1, 2)).toBe(3);
  })
  minus()
});
$ npm run test

> jest-playground@1.0.0 test
> jest --collectCoverage

 PASS  ./sample.test.js
  sample
    ✓ sum (2 ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |     100 |      100 |     100 |     100 |                   
 sample.js |     100 |      100 |     100 |     100 |                   
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.527 s, estimated 1 s

次に、minusのテストが通らない場合を想定する。
双方にJestのExpectを使った場合はカバレッジは100%になる。

describe('sample', () => {
  it('sum', () => {
    expect(sum(1, 2)).toBe(3);
  })
  it('minus', () => {
    expect(minus(2, 1)).toBe(5);
  })
});
$ npm run test

> jest-playground@1.0.0 test
> jest --collectCoverage

 FAIL  ./sample.test.js
  sample
    ✓ sum (1 ms)
    ✕ minus (2 ms)

  ● sample › minus

    expect(received).toBe(expected) // Object.is equality

    Expected: 5
    Received: 1

       7 |   })
       8 |   it('minus', () => {
    >  9 |     expect(minus(2, 1)).toBe(5);
         |                         ^
      10 |   })
      11 | });
      12 |

      at Object.<anonymous> (sample.test.js:9:25)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |     100 |      100 |     100 |     100 |                   
 sample.js |     100 |      100 |     100 |     100 |                   
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 passed, 2 total
Snapshots:   0 total
Time:        0.572 s, estimated 1 s

次のようにminusでNode.jsでassertが通らない場合は、sumのテストが通るにも関わらず、カバレッジは0%になる。

describe('sample', () => {
  it('sum', () => {
    expect(sum(1, 2)).toBe(3);
  })
  assert.equal(minus(2, 1), 5);
});
$ npm run test

> jest-playground@1.0.0 test
> jest --collectCoverage

 FAIL  ./sample.test.js
  ● Test suite failed to run

    AssertionError [ERR_ASSERTION]: 1 == 5

       6 |     expect(sum(1, 2)).toBe(3);
       7 |   })
    >  8 |   assert.equal(minus(2, 1), 5);
         |          ^
       9 | });
      10 |

      at sample.test.js:8:10
      at Object.<anonymous> (sample.test.js:4:1)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |       0 |        0 |       0 |       0 |                   
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.599 s, estimated 1 s
まとめ
  • JestはJestのAPIを用いたテストに対してカバレッジを計測しているのではなく、テストで呼び出されたか否かでカバレッジを計測している。
  • Node.jsのassert moduleを使ってテストが通らなかった場合は、カバレッジの計測は機能しない。
  • Stmts, Branchは追って調査していく

I contribute to denoland 1 month in a row


Summary

https://github.com/pulls?q=involves%3Awafuwafu13+-user%3Awafuwafu13+author%3Awafuwafu13+org%3Adenoland

  • 24PR Merged
    • deno_std
      • 5feat
      • 1fix
      • 6chore
      • 6test
      • 4docs
      • 1refactor
    • deno_lint
      • 1test
  • 17/311 Contributers in deno_std


What I'll do

:+1: :-)

GCI 2021 Summer 修了した

今までWebアプリケーションには関わってきたけど、機械学習に関しては無知だったのでGCI 2021 Summer | 東京大学グローバル消費インテリジェンス寄付講座に参加してみた。
申し込みしたら誰でも参加できる感じで門戸は広く、修了した人は5人に1人くらいだった。
週1の課題(満点)と2回のコンペと最終課題を提出したら修了できた。
講義と資料の質はめちゃくちゃ高くて、自分は使わなかったけど授業外の個別サポートもあったから無料にしては体験が良すぎた。
難易度は、講義の内容を補足まで理解しようと思ったら難しかったけど、宿題をこなすにはちょうどよかった。
講義と宿題合わせて毎週3~5時間、最終課題は丸2日くらいかけてやった。
コンペに関してはKaggleの経験が皆無だったけど、ヒントとか他の人のコードが見れる機会があったから意味を理解して提出はできた。
Numpy/Pandas/Matplotlib/教師あり学習/教師なし学習/SQL/仮想化・クラウド基礎/MLOps基礎/マーケティング基礎、応用の一部 を1回の講義を受けて進めていったので、機械学習を理解できたというよりその上部を一周できたという感じだった(とても満足)。
AWS EducateでAWSもいじれた。
ゲスト講師の回もなかなか話が面白かった。
ちなみに最終課題はこれを提出した(マサカリは許さない)。
https://www.canva.com/design/DAEk_g1dwT4/a2fodMbJli3y_5hnwteDlQ/view?utm_content=DAEk_g1dwT4&utm_campaign=designshare&utm_medium=link&utm_source=publishsharelink
修了した後は特に個人間のやりとりはないが、修了生のSlackがあってそこに松尾研が関わっている会社のインターン募集とかが流れている。
個人的には金融輪読会に興味があってだいぶ前に応募したつもりが反応がないのでこれからアプローチしたいと思っている。
サマースクール2021 深層生成モデルにも応募して現在も講義が続いているが、難易度が急激に上がって何もわからないから離脱して最近は数学の独学をしている。

サイボウズのフロントエンドエキスパートチームのインターンに参加しました

8/30日から9/3日の5日間、申し訳ございませんお探しのページが見つかりませんでしたに参加させていただきました。

参加するまで

フロントエンドエキスパートチームへの強い興味のきっかけは、おそらく2021年1月20日にこの記事を読んだことだと思います(もっと前に知ってはいただろうけどいつから知っていたということを覚えていない)。
大規模 Closure Tools プロジェクトに Prettier を導入するまでの道のり - Cybozu Inside Out | サイボウズエンジニアのブログblog.cybozu.io
この記事の次の部分を京阪三条駅に着きかける電車の中で読んで驚いた記憶があります。

偶然にも私は Prettier のメンテナーでリリースを担当しているので、リリースとそのための作業を業務時間に行い迅速にリリースをすることができました。

自分が初めて簡単なPRをOSSに投げたのが2020年11月3日なので、OSSに少し興味はあったものの、こうしてOSSの世界でバリバリに活躍している同年代の方がいるとはっっという感じでした。
今までずっとフロントエンドだけをやってきたわけではないので、そこからは会社でフロントエンドを書いたり書かなかったり、フロントエンドマンスリーを見たり見なかったりという生活をしていました。
が、OSSへの憧れと単純な楽しさが相まってOSSJavaScriptを書くことは継続してやっていました。
そしてまさかのインターン募集があったので、迷わず第1志望で提出しました。
通るとは思っていなかったですが、書類と1時間の面接だけで参加が決まったので、簡単にでもOSSしててよかったです。

参加してから

ざっくり言うと「技術的負債の解消段階で生じた問題を、構成を変えることにより解消するため、技術選定から導入、実装、他チームへの共有、ADRの作成まで」をしました。
フルリモートで、社員さん含め5,6人くらいが常時同じzoomにいて、インターン生2人がドライバーを交代しながら作業すると言う形でした。
モブプロが初めてだったので、ドライバーをする際、1人で考え込んでしまう時間があって難しい部分はありましたが、全体を通じて他の方から得れる部分が多々あった(というかほぼそれだった)ので、とても体験が良かったです。
あとはそもそも自分の知識が足りないところがあった(特に技術選定時にNXとかRushが出てきた時や、このOSSではこう使われているから...とかの会話はついていけなかった)のでまだまだ甘い!!!と感じました。
業務以外にもイベントがたくさんあって楽しかったです。
単純に普段からフロントエンドの先頭を走ってる方々の話を聞くのもそうですし、フロントエンドマンスリーにも参加させていただいたのは貴重な機会でした(業務時間外にもPrettierで関われた)。
フロントエンドエキスパートチームだけではなく、他のチームの業務内容や連携を知れたのもよかったです。

参加した後

フロントエンドが大好き、かつ世界の動きに置いていかれたくないので、もっとアンテナの強度を高めていきたいと思います。
社員の方々ももちろんですが、もう1人のインターン生の方の知識というか感性に敵ってない予感がしているので良い刺激になっています。
特にフロントエンドのエコシステムにまつわるOSSが好きなので、関われた方々と同じ世界線で生きていけるように色々頑張りたいです。
貴重な5日間に関わってくださった方々、ありがとうございました!!!