見出し画像

エンジニア全員でAIに挑戦!『ゼロから作るDeep Learning』輪読の成功ストーリー

こんにちは、プログリットのエンジニア Kokiです。
今日はO'Reilly Japan - ゼロから作るDeep Learningを輪読してプロダクト開発部エンジニア全員でAIについて勉強している事について話したいと思います。


輪読会に至った背景

そもそも輪読会に至った経緯としては、社内数人でこんな話をしたときでした。

  • (Koki)あら、こんなところに「ゼロから作るDeep Learning」という本がある

  • (Shima)それ、先日買っておきました!面白そうだったのと、今話題のLLMでも出てくるバッチや過学習などと言ったものの基礎となるのがDeep Learningと呼ばれるもので、これからサービス作るなら知っておいて損はないかと思います!

  • (Koki)ほえー。なるほどです!読んでみます!

  • (Kossy)それ面白そうですね!次貸してくれますか?Daisukeさんも興味ありそう

  • (Koki)自分読むの時間かかるので、結構先になるかも…

  • (Shima)輪読とかやって同時に読み進めるのいいかもですね

  • (Koki&Kossy)良いですね!

と軽いノリから始まりました(笑)
せっかくならと、プロダクト開発部のエンジニアメンバーに声かけてみたら「ぜひ参加したい」と言ってくれました。
※Shima: 弊社エンジニアマネージャーで、普段は「Shimaさん」と呼んでいます。Shimaさんについてはこちらの記事をご覧ください!

Kossy: 弊社PdMで社内では「Kossy(コッシー)さん」と呼んでいます。Kossyさんについてはこちらの記事をご覧ください!

輪読会の運営について

輪読に参加すること自体初めての経験だったので、他事例を参考にさせてもらいました。特にこちらの記事に書かれていた「輪読会は、みんなで協力して1冊の本を理解することが目的」のもと下記の進め方で完読しました。

  • 2週に1度のペースで1時間枠で開催

  • 章ごとに発表者を決め解説を45分程度行う。15分は質疑応答など

    • 45分で足り無さそうであれば、前半/後半で分けて行う

  • 参加者は事前読みを必須とし、事前に疑問・質問シートに記入する

  • 発表は挙手制。誰も手を挙げなければモチベ高そうな人に依頼

  • 発表資料等は、ドキュメント共有システムであるesaを使う

  • 章ごとなど区切りの良いところでモブプロを開催

実際の勉強会の発表資料。本の見出し通りに構成するのが一般的になりました。

メンバーから離脱しそうとの声が…

上記の運営手法を初期から取り組めたわけではなく、適宜メンバーからのFBをもらい改善していきながら行いました。
その例に、「2章パーセプトロン」の解説後、参加者数名にヒアリングしてみたところ離脱しそうで不安という声が上がりました。
よく話を聞いてみると、45分の中で聞きながら整理し理解するのは大変で、章が進むに連れて理解せずに進むことが怖いというものでした。
この課題感を解決するために、「参加者は事前読みを必須とし、事前に疑問・質問シートに記入する」というルールを設定し15分の質疑応答時間で疑問点を出来るだけ残さず次の章を迎えるようにしました。
また、この時書籍をまだ持っていないメンバーもいたので、経費購入のサポートも行ったりと足並みを揃えるのも大切でした。

その結果

1冊目を終えたときのアンケート

発表者の丁寧な解説もあり、1冊目に関しては離脱者ゼロで終えることができ、各々学びを得ることができたようです。
一方で学び残しについてはゼロにすることは出来なかったことは悔しいですが、皆さん激務のなか1時間も空けてくれた事や発表してくれた人は準備がとても大変だったと思うので、離脱者ゼロだったことが何よりも有り難いなと感じています。

章ごとに分からないが分かるに変っていく

この本はとても分かりやすく書いてくれていますが、3章くらいから何度読んでも内容が理解できませんでした。
というのも、「3章ニューラルネットワークで出てくる多次元配列の計算」で使う行列計算はこの本で初めて知りましたし、「4章ニューラルネットワークの学習」から出てくる微分については、高校生の授業で出たかなーぐらいで、導関数についても学び直しといった具合でしたので…
なので、僕も学び残しゼロかと聞かれたらゼロとは答えられない気がします(笑)
この点、輪読会というは章ごとに少しずつ調べながら学べば良いことや、自分が分からない所も他メンバーが理解を手伝ってくれたりするので、1人で読むとは違う学びがあるように思えます。
また発表にチャレンジすることは、メンバーに説明出来るだけの理解度が必要になるため、自分ひとりで読んでいたら素通りしていた部分を素通りせず調べて理解する良い意味でのプレッシャーがあるのも良かったと思います。

モブプロもやってみました

区切りの良いところでモブプロを2回ほど行ってみました。
設定背景としては、3章終わった頃に中間アンケートでFBを募ったところ理解が浅い箇所があるという声もあり、先程の疑問・質問シートや未発表者は回収出来ていない部分もあるようなので、モブプロという形で疑問点を解消できるか試してみました。

1回目:1章〜3章

  • Playground環境はGoogle Colaboratory

  • 課題は3層ニューラルネットワークの実装と手書き画像の認識を問題

という形で行ってもらいましたが、1回目は少し失敗でColaboratoryがモブプロには向いておらず、タイピストの交代にもたついたり、課題が写経に陥ってしまった等の反省点がありました。

2回目:第4章

1回目の反省を活かし、Visual Studio Live Share & remotemobprogramming/mobというツールを使い下記の流れで実施しました。

  1. ホストがVisual Studio Live Shareの招待

    1. ターミナルの共有をして頂きます。以降はホストさんPCで作業を行います。タイピストが変わってもホストPCは変更しない。

  2. 下記のコマンドを実行してモブプロをスタートする

    • チームごとにmob start 5

  3. 5分経ったら、ホストPCで「モブ ネクスト」という通知が届き、次のモブに変わる

  4. タイピストはmob nextをターミナルで実行し次のタイピストに変る準備をする

また問題も写経にならずに値を微妙に変えたり、ふわっとした問題文にしてモブ同士が議論できる内容に工夫もしました。

# 第4章のモブプロ
import numpy as np

def sum_squares_error(y, t):
    """二乗和誤差"""
    # TODO: 問1:ここを実装してください
    return 0

def cross_entropy_error(y, t):
    """交差エントロピー誤差"""
    delta = 1e-7
    return -np.sum(t * np.log(y + delta))

def numeric_diff(f, x):
    """数値微分"""
    h = 1e-50
    return (f(x+h) - f(x)) / h

def numeric_gradient(f, x):
    """数値勾配"""
    h = 1e-4
    grad = np.zeros_like(x)

    for idx in range(x.size -1):
        tmp_val = x[idx]
        # f(x+h)の計算
        x[idx] = tmp_val - h
        fxh1 = f(x)

        # f(x-h)の計算
        x[idx] = tmp_val + h
        fxh2 = f(x)

        grad[idx] = (fxh1 - fxh2) / (2*h)
        x[idx] = tmp_val
    
    return grad
    

if __name__ == '__main__':
    y = np.array([0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0])
    t = np.array([0, 0, 1, 0, 0, 0, 0, 0, 0, 0])
    result = sum_squares_error(y, t)
    # assert result == 0.09750000000000003

    def function_1(x):
        return 0.01*x**2 + 0.1*x
    
    result = numeric_diff(function_1, 5)
    # TODO: 問2:この2つはAssertErrorになります。なぜでしょうか?
    # assert result == 0.1999999999990898
    # result = numeric_diff(function_1, 10)
    # assert result == 0.2999999999986347

    # f(x, y) = x - 2yの関数に対して、x=3, y=4のときのxに対する偏微分を求めよ
    def function_tmp(x):
        # TODO: 問3:ここを実装してください
        return 0
    
    result = numeric_diff(function_tmp, 3)
    # assert result == 0.9999999999999997

    def function_2(x):
        return x[0]**2 + x[1]**2
    
    # TODO: 問4:この2つはAssertErrorになります。なぜでしょうか? 
    result = numeric_gradient(function_2, np.array([6.0, 8.0]))
    # assert np.allclose(result, np.array([12., 16.]))
    # result = numeric_gradient(function_2, np.array([0.1, 9.0]))
    # assert np.allclose(result, np.array([0.2, 18.]))

    # TODO:問5:f(x, y) = e^(xy)の最小値を求めてください

そのおかげもあり、2回目はスムーズに進行し、下記のようなコメントもいただき、楽しく学びを得てもらえたようです。

2回目モブプロのアンケートで頂いたコメントのひとつ

2冊目の輪読会にむけて

1冊目終了後のアンケート結果

2冊目はO'Reilly Japan - ゼロから作るDeep Learning ❷自然言語処理編を輪読する予定です。
ChatGPTやCopilotなど日々の業務での利活用するのが当たり前の時代になってきています。AI全般に関して「なんとなくこうかな?」と手探り状態になるのではなく、こういった勉強会を通してプロダクト開発部全体で基礎知識をつけて、AIを活用したプロダクトに自信を持ってリリース出来るように準備していきます!
ここまで読んでくれてありがとうございました。

プログリットの成長を加速させる開発のお仕事を担う仲間を募集しています!

プログリットでは、プロダクト開発のメンバーを募集しています!
「世界で自由に活躍できる人を増やす」というミッションに共感してくださる方、組織の中でお互いに切磋琢磨しながら成長していきたいという方は、ぜひカジュアル面談でお話しましょう!


この記事が気に入ったらサポートをしてみませんか?