2019/08/02 これからの開発チームのあり方を考える @ Sansan Innovation Lab
ϦϒηϯεͰͷMLγεςϜ։ൃɾӡ༻ͱݚڀɾ։ൃΞγελϯτͷऔΓΈShotaro Tanaka / @yubessy / Ϧϒηϯε͜Ε͔Βͷ։ൃνʔϜͷ͋ΓํΛߟ͑Δ @ Sansan Innovation Lab
View Slide
ࣗݾհాத ଠ / @yubessy• גࣜձࣾϦϒηϯε• ςΫϊϩδΧϧϚʔέςΟϯά෦ σʔλϓϥοτϑΥʔϜάϧʔϓ• ࣄ• Ҏલ: σʔλੳج൫ (Livesense Analytics) ͷ։ൃɾӡ༻• ݱࡏ: ػցֶशج൫ (Livesense Brain) ͷ։ൃɾӡ༻• ژΦϑΟεۈ• ݚڀɾ։ൃΞγελϯτͷϝϯλʔ
͢͜ͱ• ػցֶशγεςϜͱͦͷ࣮ߦج൫ͷ։ൃɾӡ༻Λ͍ͯ͠ΔνʔϜ• ژΦϑΟεத৺ʹݚڀɾ։ൃΞγελϯτͱֶͯ͠ੜΞϧόΠτΛ࠾༻• ͳͥΞγελϯτͷΈ͕͋Δͷ͔ɾͲΜͳࣄΛ͍ͯ͠Δ͔• ۀ্ͲΜͳোน͕ଘࡏ͢Δ͔ɾͦΕΛͲ͏ࠀ͍ͯ͠Δ͔
Ϧϒηϯεͷڥ
ӡӦαʔϏε
৫ߏ• ࣄۀ෦• ΞϧόΠτࣄۀ෦ (ϚοϋόΠτ)• స৬ձٞࣄۀ෦ (స৬ձٞ)• ෆಈ࢈Ϣχοτ (Door ି, IESHIL)• ...• ԣஅ৫• ςΫϊϩδΧϧϚʔέςΟϯά෦• σʔλϓϥοτϑΥʔϜάϧʔϓ ← MLؔ࿈ͷνʔϜ͜͜ʹॴଐ• σʔλϚʔέςΟϯάάϧʔϓ• ΠϯϑϥετϥΫνϟάϧʔϓ• ωΠςΟϒΞϓϦάϧʔϓ
MLνʔϜɾMLج൫νʔϜࣾһ• MLΤϯδχΞ: 2໊• MLج൫ΤϯδχΞ: 2໊• શʹۀ͍ͯ͠ΔΘ͚Ͱͳ͘ɺॏͳΔ෦͋ΔΞϧόΠτ = ݚڀɾ։ൃΞγελϯτ• ژΦϑΟε: 4໊• ౦ژΦϑΟε: 1໊
αʔϏεͱMLγεςϜMLɾMLج൫νʔϜ͕֤αʔϏεʹ༷ʑͳMLγεςϜΛఏڙ• ϨίϝϯυΤϯδϯ → αΠτɾΞϓϦͳͲͰͷٻਓਪનʹར༻• Ԡืɾ࠾༻ͳͲͷਪఆɾ༧ଌϞσϧ → ࠂग़ߘͳͲʹར༻• όϯσΟοτπʔϧ → A/BςετͷޮԽʹར༻ෳͷMLγεςϜΛগਓͷνʔϜͰ։ൃɾӡ༻Ͱ͖ΔΑ͏• MLγεςϜΛߏཁૉ͝ͱʹղ͠ૄ݁߹Խ• ڞ௨ͷΠϯϑϥͰෳγεςϜΛӡ༻ৄࡉ ࣄۀԣஅ৫ͰͷMLγεςϜ։ൃɾӡ༻ͱج൫ઃܭ Ͱ
MLγεςϜͷߏMLγεςϜͷߏཁૉΛׂ͠ʮίϯϙʔωϯτʯͱݺΜͰ͍Δ• ਪનΞϧΰϦζϜ, લॲཧ, ݁ՌϏϡʔϫ ͳͲ͕֤ʑ୯Ұίϯϙʔωϯτ• ̍ίϯϙʔωϯτ = ̍ϨϙδτϦ = ̍ίϯςφΠϝʔδ ͷߏͰ౷Ұ֤ίϯϙʔωϯτຖʹ ࣮ ʙ ςετ ʙ ϦϦʔε ͷαΠΫϧ͕݁• ίϯϙʔωϯτຖʹαϯϓϧσʔλࣗಈςετΛඋ• ίϯϙʔωϯτͷಈ࡞ݕূʹඞཁͳͷ docker run ͚ٕͩज़໘ Argo Workflow ʹΑΔػցֶशϫʔΫϑϩʔཧ ࢀর
ݚڀɾ։ൃΞγελϯτ
֓ཁݚڀɾ։ൃΞγελϯτʢژΦϑΟεʣืूཁ߲• ػցֶशɾσʔλΤϯδχΞϦϯά͓ΑͼͦΕʹਵ͢Δݚڀɾ։ൃ• िؒʙϲ݄୯ҐͷϛχϓϩδΣΫτܗࣜ• جૅతͳΤϯδχΞϦϯάεΩϧ +α Ͱ׆͔ͤΔٕज़͕͋Δ͜ͱ• ʢવͳ͕Βʣֶۀ༏ઌ≠ ৽ଔ࠾༻• ͋͘·ͰۀΛ௨ͯ͡νʔϜɾαʔϏεʹߩݙ͢Δͷ͕త• ࠾༻తͰͷֶੜͷғ͍ࠐΈ͠ͳ͍ʢͪΖΜೖࣾͯ͘͠ΕͨΒخ͍͠ʣ
ۀ༰ʮՌ͕ग़Δ͔Θ͔Βͳ͍͕ɺઓ͢ΔՁ͕͋Δʯ͜ͱ• ͬͯΈ͍͕ͨͯ͘͠खΛ͚ΒΕ͍ͯͳ͍ٕज़ݕূɾσʔλੳ• MLγεςϜͷิॿπʔϧʢσʔλ֬ೝɾϝτϦΫεऩूʣͷ։ൃۀܗଶ্ෆ͖ͳࣄආ͚Δ• ظݶ͕͋Δɾۓٸੑ͕ߴ͍• ࣦഊ࣌ͷϦεΫ͕େ͖͍• ਂ͍υϝΠϯࣝɾଞ෦ॺͱͷີͳ࿈ܞΛཁ͢Δ
ྫ: Julia ͷฒྻܭࢉػೳͷݕূɾಋೖ• ࣾͰ Julia ͰϨίϝϯυΞϧΰϦζϜΛ࣮͍ͯ͠Δ• ϓϩηεɾεϨουฒྻػೳʹΑΔߴԽΛݕূ࣮͠ࡍʹಋೖ
ྫ: ΫνίϛͷผϞσϧͷݕূ• ΫνίϛαΠτͷҙຯෆ໌ͳߘͳͲΛࣗಈఆ͢ΔϞσϧΛ࡞ͬͯΈΔ• ಛྔɾΞϧΰϦζϜͷௐͰ࠶ݱɾద߹ΛͲͷఔ্͛ΒΕΔ͔ݕূ
ྫ: Ϩίϝϯυͷ݁ՌϏϡʔΞͷվળ• Ϩίϝϯυͷ݁ՌΛ֬ೝ͢Δ؆୯ͳ Web ΞϓϦΛ։ൃ• ΞϧΰϦζϜʹΑΔϥϯΩϯάมԽͷൺֱػೳͳͲΛࡌ
Ξγελϯτۀʹ͓͚Δ੍࣌ؒ ͷ੍• ීஈ͔Βतۀɾݚڀ߹ͷग़ୀࣾ࣌ࠁมߋதൈ͚͕ൃੜ• ࣌ظʹΑͬͯࢼݧจࣥචʹΑΔظෆࡏ͕ൃੜۀൣғ ͷ੍• εΩϧ͕ݚڀدΓͰҰൠతͳ Web ։ൃʹෆ׳Εͳ͜ͱ• ݖݶ্ϝϯλʔʹ͔͠Ͱ͖ͳ͍࡞ۀ͕Ұఆൃੜ→ ͦΕͧΕͷ੍ʹͲ͏ରԠ͍ͯ͠Δ͔Λհ
࣌ؒͷ੍
࣌ؒͷ੍ීஈ͔Βतۀɾݚڀ߹ͷग़ୀࣾ࣌ࠁมߋதൈ͚͕ൃੜ• ͑Δ͕࣌ؒগͳ͍ͷͰࢦ͕ࣔͪൃੜ͢Δͱޮ͕མͪΔ• ࣾһͱಉ࣌ؒ࣠͡ͰಉظతʹࣄΛਐΊΔͷ͕͍࣌͠ظʹΑͬͯࢼݧจࣥචʹΑΔظෆࡏ͕ൃੜ• ෆࡏதͷঢ়گมԽʹϓϩδΣΫτ͕ࠨӈ͞ΕΔͱՌ͕ແବʹͳΔ͓ͦΕ• ظ͕ۭؒ͘ͱϝϯλʔԿΛ͍͔ͬͯͨΕ͕ͪ→ ϓϩδΣΫτཧΛ֤ͯࣗ͠ͷϖʔεͰਐΊΒΕΔΑ͏ʹ
ϛχϓϩδΣΫτܗࣜͰͷ࣮ࢪݸผλεΫͰͳ͘ϓϩδΣΫτͱͯ͠എܠɾΰʔϧΛ໌จԽ• ͜Ε͕Ͱ͖ΔͱνʔϜαʔϏεʹͱͬͯԿ͕خ͍͠ͷ͔• ͲΜͳΞτϓοτ͕Ͱ͖Εޭͳͷ͔ஞҰࡉ͔͍ࢦࣔΛ͠ͳͯ͋͘Δఔ֤ࣗͷஅͰਐΊΒΕΔΑ͏ʹ• ̎ʙ̏ఔࢦ͕ࣔͪൃੜ͠ͳ͍͜ͱΛ҆ʹ• िʹ̍ճϖʔεͰৼΓฦΓΛ࣮ࢪ
# ϓϩδΣΫτ: Julia + Docker ͷฒྻԽػߏͷݕূɾಋೖ## എܠData Platform άϧʔϓͰ֤αʔϏεͰར༻͢ΔϨίϝϯυΞϧΰϦζϜΛ Julia Ͱ࣮͠ Docker ίϯςφͱͯ͠ӡ༻͍ͯ͠·͢ɻhttps://github.com/livesense-inc/brain.recommenderMatrix Factorization ͷΑ͏ͳΞϧΰϦζϜɺֶश༧ଌͷҰ෦ͷॲཧΛฒྻԽ͢Δ͜ͱ͕ՄೳͰ͢ɻ͜ͷ͏ͪੵL2ϊϧϜʹΑΔϕΫτϧ୳ࡧʹ͍ͭͯ faiss Λར༻Ͱ͖·͕͢ɺϥΠϒϥϦ͕ͳ͍Α͏ͳέʔεͰࣗͰॲཧΛ࣮͢Δඞཁ͕͋Γ·͢ɻJulia ʹ༷ʑͳฒྻԽػߏ͕༻ҙ͞Ε͍ͯΔͨΊɺͦΕΒΛͬͯΞϧΰϦζϜΛߴԽͰ͖Εɺ։ൃɾӡ༻ͷޮΛ্Ͱ͖·͢ɻͦ͜Ͱࠓճ Julia ͷฒྻԽػߏͷௐࠪͱɺͦΕΛ༻͍ͨߴԽͷ࣮ΛߦͬͯΒ͍·͢ɻ## ΰʔϧ- Julia + Docker Ͱར༻ՄೳͳฒྻԽػߏΛௐࠪ͠Ϩϙʔτʹ·ͱΊΔ- brain.recommender ͷ prediction ΛฒྻԽʹΑΓߴԽ͢Δ## ڥ- Julia όʔδϣϯ: 1.0.2- ίϯςφͷϕʔεΠϝʔδ: julia:1.0.2 (https://hub.docker.com/r/library/julia/)...
ΞτϓοτΛஈ֊తʹϓϩδΣΫτதʹෳճͷνΣοΫϙΠϯτΛઃ͚Δ• ։ൃܥϓϩδΣΫτͰϦϦʔεΛԿஈ֊͔ʹ͚Δ• ੳɾݕূܥϓϩδΣΫτͰෳճϨϙʔτΛ࡞ϓϩδΣΫτ͕தஅͯͦ͠ͷ࣌·ͰͷՌ͕׆͖ΔΑ͏ʹ͢Δ• ͍͖ͳΓػೳ࣮ʹೖΔͷͰͳٕ͘ज़ݕূ͔Β࢝ΊΔ• ݕূٕͨ͠ज़ͷಋೖ·ͰͰ͖ͳͯ͘ݟ͕ΔΑ͏ʹ
## εςοϓ### 1 - ฒྻԽػߏͷಈ࡞ݕূҎԼͷ Julia ެࣜυΩϡϝϯτʹهࡌ͞ΕͨฒྻԽػߏ͕ɺDocker ίϯςφͰಈ࡞͢Δ͔֬ೝ͍ͯͩ͘͠͞ɻhttps://docs.julialang.org/en/v1/manual/parallel-computing/index.html#Multi-Threading-(Experimental)-1ࠓճͷݕূରϚϧνεϨου·ͨϚϧνϓϩηεʹΑΔฒྻԽͰ͢ (άϦʔϯεϨου, ΫϥελίϯϐϡʔςΟϯάର֎Ͱ͢)ɻ### 2 - ฒྻԽػߏͷύϑΥʔϚϯεݕূ1Ͱݕূͨ͠ॲཧͷ͏ͪಛʹ SharedArrays, SparseArrays ͷ read/write ʹ͍ͭͯɺҎԼͷΑ͏ʹύϑΥʔϚϯεݕূΛߦ͍ͬͯͩ͘͞ɻ...·ͨ2ͰͷฒྻԽରͷؔͷॻ͖ํͱͯ͠ɺ࣍ͷΑ͏ͳҧ͍ʹΑΓ݁Ռʹ͕ࠩग़Δ͔Λௐ͍ͯͩ͘͞ (ฒྻॲཧͰ࠷దԽϚΫϩ͕ޮ͔͘ΛௐΔͨΊ)ɻ...### 3 - brain.recommender ͷฒྻԽ1, 2 ͷݕূ݁ՌΛͱʹ brain.recommender ͷ࣍ͷॲཧΛฒྻԽ͍ͯͩ͘͠͞ɻprediction ͰͷϢʔβɾΞΠςϜຖͷείΞܭࢉ:...
ۀൣғͷ੍
ۀൣғͷ੍εΩϧ͕ݚڀدΓͰҰൠతͳ Web ։ൃʹෆ׳Εͳ͜ͱ• ෳࡶͳ Git ͷϒϥϯνӡ༻ʹ׳Ε͍ͯͳ͍• Python, Jupyter ݚڀͳͲͰ͏͕ Web ΞϓϦ։ൃະܦݧݖݶ্ϝϯλʔʹ͔͠Ͱ͖ͳ͍࡞ۀ͕Ұఆൃੜ• ຊ൪ڥͰͷಈ࡞֬ೝϦϦʔεͰ͖ͳ͍• ։ൃऀͱӡ༻ऀ͕ҟͳΔͱൃੜ࣌ͷରԠʹखؒऔΔ→ γεςϜߏɾϦϦʔεϑϩʔͷͰোนΛখ͘͢͞Δ
࠶ܝ: MLγεςϜͷߏMLγεςϜͷߏཁૉΛׂ͠ʮίϯϙʔωϯτʯͱݺΜͰ͍Δ• ਪનΞϧΰϦζϜ, લॲཧ, ݁ՌϏϡʔϫ ͳͲ͕֤ʑ୯Ұίϯϙʔωϯτ• ̍ίϯϙʔωϯτ = ̍ϨϙδτϦ = ̍ίϯςφΠϝʔδ ͷߏͰ౷Ұ֤ίϯϙʔωϯτຖʹ ࣮ ʙ ςετ ʙ ϦϦʔε ͷαΠΫϧ͕݁• ίϯϙʔωϯτຖʹαϯϓϧσʔλࣗಈςετΛඋ• ίϯϙʔωϯτͷಈ࡞ݕূʹඞཁͳͷ docker run ͚ͩ
ίϯϙʔωϯτ୯ҐͰͷվળ̍ϓϩδΣΫτͰ̍ίϯϙʔωϯτΛվળ → ඞཁεΩϧΛݶఆ• ֤ࣗͷಘҙڵຯʹԠͯ͡ϓϩδΣΫτΛͤΔ• ະܦݧͷٕज़ͰΩϟονΞοϓίετΛͳΔ͘খ̍͘͞ϨϙδτϦ͋ͨΓͷ։ൃਓΛݮΒͯ͠ఔΛ୯७Խ• Git flow ͷΑ͏ͳࡶͳϒϥϯνӡ༻ඞཁͳ͍• ίϯϑϦΫτ͕ൃੜ͠ʹ͘͘ɺൃੜͯ͠ղܾ͕༰қʹ
֤ϨϙδτϦͷϓϧϦΫ• Ξγελϯτ / ओͳίϯϙʔωϯτ ຖͷϓϧϦΫͷ• ਓʹΑͬͯѻ͏ίϯϙʔωϯτ͕ࣗવʹ͔Ε͍ͯΔ
ϦϦʔεͷলྗԽɾ҆શԽϦϦʔεϑϩʔΛ̎ஈ֊ʹ͚ɺϝϯλʔίϯϙʔωϯτར༻ͷஅͷΈ1. Ξγελϯτ͕ίϯϙʔωϯτʹػೳՃ2. ϝϯλʔ͕γεςϜͰར༻͢ΔίϯϙʔωϯτόʔδϣϯΛΓସ͑ϦϦʔεલޙͰ༷ʑͳ҆શࡦΛߨ͍ͯ͡Δ• ։ൃڥͰΞγελϯτ͕γεςϜͷಈ࡞֬ೝ·Ͱߦ͑Δ• ඞཁʹԠͯ͡ΧφϦΞϦϦʔεɾA/BςετͰӨڹΛہॴԽ• ສҰͷΓ͠όʔδϣϯΛ͚ͩ͢ → ରԠͷ༨༟͕ੜ·ΕΔ
ϦϦʔεϑϩʔ
·ͱΊͱFAQ
·ͱΊ• MLγεςϜͷ։ൃɾӡ༻νʔϜͰݚڀɾ։ൃΞγελϯτΛ࠾༻• ֶੜΞϧόΠτͷۀʹ͍͔ͭ͘ͷ੍͕͋Δ• ࣌ؒͷ੍• ۀൣғͷ੍• ੍Λ͏·͘ѻ͏Λͯ͠νʔϜͷੜ࢈ੑΛ্• ࣌ؒͷ੍ → ϓϩδΣΫτཧΛ• ۀൣғͷ੍ → γεςϜߏɾϦϦʔεϑϩʔΛ
FAQ• ΞγελϯτͷͨΊʹؤுͬͯΈΛ࡞ΓࠐΉʁ• ΞγελϯτʹݶΒͣ৽نࢀೖোนΛԼ͛Δ͜ͱʹҙຯ͕͋Δ• Ξγελϯτ͕͍ͳ͘ͳͬͨΒͲ͏ͳΔʁ• ৽ػೳ։ൃٕज़తνϟϨϯδʹऔΓΊΔػձ͕ݮΔ• ϝϯλʔͱͯ͠Ұ൪େมͳ͜ͱʁ• ίϯςΩετεΠον• ϝϯλʔͷࣄͬͯͲ͏ʁ• ૉʹָ͍͠