Among Us ã® Discord Overlay ã¿ã¹ã¯ããã¯ã«ã¼
ç«ãæåã Among Us ãªã®ã§ Discord StreamKit Overlay Custom CSS Generator for Among Us Streamer ä½ã£ãã¨ãã話ï¼
å¹´æ«ã«ãã£ã¨ããéã(石によるものã§ã¯ãªã)è °ãä¸ãã¦Switchãè²·ã£ãã®ã§é ä¿¡ç°å¢ãæ´ãã ããï¼ä»¥åWoWsã¨ãã¡ããã¡ãããã£ã¦ãã¨ãã¯ShadowPlayã§é²ç»ãã¦ããã¦ã¹ãã¬ã¼ã¸ãããã«Youtubeã«ä¸ãã¦ã¯æ»èµããã¦ããï¼ã§ï¼æè¿ã¯ãªã¢ã¼ã主ä½(ã¨ããããããã1å¹´ãããååã«é¡è¦ãã¦ãªã)ã ãï¼OBSã®ä½¿ãæ¹ææ¡ãã¨ãã¨ãªãããã¼ãã£ã³ã°ã¨ãã§ãè¯ããã¨ããã®ã§ã¯ï¼ã¨ï¼Among Usã¨ãã¤ã«2ã¨ãééããã£ããããªããOBS使ã£ã¦ã¿ã¦ãï¼æ åä½ããããã¢ããªã ãã使ç¨æã¯ãçµµæãã¢ããªã«è¿ããªãã®ã¯ã¾ããããªãã ãã©åºæ¥ãããããã¦æå¿ãã¦ãï¼ãã¨MBPã¯å ¨ç¶OBSã§ã®é ä¿¡ã«åãã¦ãªãï¼ã¿ã¼ããã«ã¨ãã¢ããªããã«ã¹ã¯ãªã¼ã³ã«ãã¦ã¦ã£ã³ãã¦ãã£ããã£ãã¦ãã°ããã«ã©ããããã¨ããããï¼ããã©ã®ãã¼ãã¦ã§ã¢ã¨ã³ã³ã¼ããã¡ãã£ã¨æ®å¿µãªæãã ï¼
話ãããæ»ãã¨èªåã¯ã¶ã£ã¡ãã人ç¼ç³»ãããã¾ã好ããããªãã¦ï¼ã¨ããè¨ãæ¹ãéãããªï¼é¢ç½ããããããããªãã¦ãæ£ãããï¼å¦çã®é 人ç¼BBSãæµè¡ã£ã¦ããããã§å°ã触ãããããã§å¾ã¯éªå±±ã®åç»è¦ããã¨ãç¨åº¦ï¼ããã§ã Among Us ã¯ããã§ãã¦ããªã¼ã¨æãï¼ã²ã¼ã å´©å£ç´ã®ãã°ã¨ãåæãºã¬ãã ãã¶ããã¿ããã ãã©ï¼ãªããããããã®ã§ãããã ãããããã®ã§ã£ã¦æããããï¼ã¯ãã¹ãã©ãããã©ã¼ã ã§ã大ãã¦å·®ãåºãªãããããã·ã³ãã¯ã¼ãããªããï¼ãã£ã©ãã«ã¯ã¤ã¤ãï¼
ã§ï¼ Among Us ã ã¨çºè¨è¼ãããããdiscordãoverlayãããã®ã¯å½ç¶ãªãã ãã©ï¼discordããã ã¨ã¯ã«ã¼ã®è²ãããããªãã®ã§ä½è²ãçºè¨ããããããããã«ããã«ã¯ã©ããã§ç´ä»ãã¦ãããªãããªããªãï¼ã¨ãã£ã¦ãåå¯ãã§ããä½ããããããã§ããªãï¼discordã®ã¦ã¼ã¶IDæ¾ã£ã¦ãã¦Discord StreamKit Overlayã«å¯¾ããã«ã¹ã¿ã CSSã«åããã¨ãããããããã©ãã主æµã¿ãããªãã ãã©ï¼ã¡ãã£ã¨ã¤ã¤åããCSSã§ããããã¨ããã¨ä½ç®æã«ãåãIDãåããªãããªããªããªã£ã¦ä¸ã 大å¤ã«ãªãï¼åã£ãè¦æ ãã§ãªãã¦ãï¼ãã¬ã¤ã¤ã¼ã§ã¯ãªã観æ¦è ããã£ã³ãã«ã«å ¥ã£ã¦ãã¨ãã«ãã®è¦³æ¦è ã¯Overlayããããªãã¨ãããã ãã§ãç´ä»ãã«å ãã¦æä½2ç®æåãã«ãªãï¼èªåãCSSç¥ããã ãã§ä¸æããããããããã®ãããããªããã©ã¡ãã£ã¨æ¢ã£ãæãç¹ã«ããããã®ããªãããã ã£ãï¼
ãªã®ã§ï¼ã¾ãåç´ä½æ¥ã ãç°¡åãªã¸ã§ãã¬ã¼ã¿ã§ããããï¼ã¨ï¼Reactã©ããªã£ã¦ãããªã¤ãã§ã«âã®SPAä½ã£ã¦ã¡ãã£ã¨ã«ã¯ã¤ã¤æãã®çºè¨ã¢ãã¡ã¼ã·ã§ã³ã«ãªãã«ã¹ã¿ã CSSã®ã¯ã«ã¼è²ã¨discord IDãã·ã¥ãã¨é ç·ã§ããããã«ããï¼ããã¯ããæå©ãããç½ç½®ããã¦ããã¦ï¼
è© å±ã¯ä¸å¯è§£ã ã£ããããã®å¹åã«ã¯ééãããªãã£ãã
ãã£ããå¹´1ã ãã©ããã¾ãé·ããã¨æ¸ããªãã®ãã¢ã¬ãªã®ã§ãã¾ã«è¿æ³ãããã¯æ¸ãã¦ããããã¨
2020å¹´ã¯ä¸ã®ä¸çã«ãããã ãã©ï¼å人ã¨ãã¦ãããã¾ãè¯ãæãã§ã¯ãªãç·ãã¦è¬ã®ç³ã«æ©ã¾ãããå¹´ã§ãã£ãï¼
æ¨å¹´æ«å¹´å§ãããããVC6ã¨ããããªãã¡ã¬ã³ã¹ãå ¬éããã¦ãªãè¬ãªå¥´ã®ãæ°æã¡ãã¨ã¹ãã¼ããä½æ¥ããå§ã¾ã£ã¦ï¼æ¥é ã¾ã§ã²ã¨ã¨ãã足ã¾ãããæ´åããããã¦ããï¼
ããã«ãããã¨ããããã§ããªããã©ãéä¸ãéããªã/å ¥ãè¾¼ã¿éããªãããã«ãããã«ã¯ã©ãããããã¡ãã£ã¨ç·´ã£ã¦ããï¼ã¨ããã®ãï¼VC4ã®ã¨ãã¡ãã£ã¨éä¸ãéãã¦*1é æ¤ããªã¯ããã¦ãã¾ã£ããã¨ããã£ãããã§ï¼ã©ããä½æ¥å 容ã»éã¨éä¸åã«å¯¾ãã¦ããã«èããç¶æ¦è½åãç¡ããããï¼ä»å¹´ã¯åºç¤¾ãå ¨ãããªããªã£ã¦éé³ãå²ãè¾¼ã¿ãå ¥ãé£ããªã£ã¦ãã¾ã£ãã®ã§ãªãããæèçã«éä¸ãéããªãããã®å·¥å¤«ãå¿ è¦ã ã£ãï¼æçµçã«ã¯VTuberã®é ä¿¡ã¨ããBGMã«ãã¦ãã*2ã¨é©åº¦ã«éä¸ãåã£ã¦ããã¦ä½æ¥ã«å ¥ãè¾¼ã¿éããä¸åº¦è¯ãå¡©æ¢ ã¨ãããã¨ãããã£ãã®ã§ä»ããããªéç¨ã«ãã¦ãï¼é常ï¼æè¡å±ã«å¯¾ãã¦ã¯ãã©ããã£ã¦éä¸ããã/éä¸ã§ããæéã確ä¿ãããããåé¡ã«ãªããã¨ãå¤ãã®ã§ï¼ããã¨ããæå³éæ¹åã®å·¥å¤«ãå¿ è¦ã¨ããã®ããªãã ããªã¨ããæãã§ã¯ããï¼
ãããªãããªãã£ã¦ãä»åã¯é æ¤çã¯ç¡äºã ã£ãã®ã ãï¼ä¸æ¹ã§å¥ã®åé¡ãé¬æãã¦ãã¾ã£ããã ãï¾ï½°ï½»ï¾
ããæ©æã«æ¿çã§èµ·ãããã¦ã³ã¤ããããã¤ãï¼ã§ããã ãè¿ãçã¿ã®è¡¨ç¾ã¨ãã¦ã¯ãéçãããã£ãæã®çã¿ãä¸ç¬ã§çµãããã«ç¶ç¶ãããã¨ããã¤ãã§åãæ°ã¨èæ±ãæ¢ã¾ããªãï¼ææ¥è»å¬åã©ã¤ã³ãæ¬å½ã«è¿·ã£ãããã®æç¹ã¾ã¨ããªå¤æåãããã¨ãããããªãã£ãã®ã§ï¼ã¨ã«ããä½ãããããããªã対象ã«è¬ããªãã*3è¿æã®ç é¢ãéãã¾ã§ãå¸å£ã«ããã¾ã£ã¦ãããã¾ããã¨ã«ãªã£ãï¼ãã®å¾ï¼æ¡è¡ãããCTæ®ã£ããã¨ãããçµæï¼ãã¼ã¼ã³ã¡ã¤ãã³æå¶ã®ãã¼ã«ã¨ãã¦åé«ãå°¿çµç³ã左尿管ã«1ã¤ã¨ä¸¡è èã«1ã¤ãã¤è¨3ã¤ç¡åé å¸ããã¦ãããã¨ãããã£ãï¼å¿è«ã¬ãã£ã¯å¼ããªãï¼ç¹ã«å°¿ç®¡ã«æããããä¸ç³ãçã¿ã®åå ã§ãã£ãï¼è¬ãå¦æ¹ãããããä¸çªã®è¬ã¯æ°´ã§ãï¼æ°´ã飲ãã§éåãã¦å°¿ç®¡ããæ¾ãåºãã¦ä¸ãããã¨ã®è§£æ±ºçãæ示ããï¼æ°´ã¯ã¨ãããã¨ãã¦ãã®æ¿çä¸ã§éåã£ã¦æ£æ°ã§è¨ã£ã¦ãã®ãã³ã¤ãã¨ãæã£ããï¼çã¿æ¢ããå¦æ¹ããããé·ç·ã ã£ãã®ã§å ã ãã¦ãã©ã³ãã³ã°ã¯ç¶ç¶ãããã¨ã«ããï¼æ¬¡ç·ã ã£ããèããããªãã£ããããããªãï¼å¥ã«å¼·ããªããçç±ã¯ããããªãã£ããã¤ãããªã£ãã®ã¯ç¢ºå®ã«Oleï¼ããã§ãªãã ããã è¡å°¿ãåºã¦ãããããã®ã®ä»ã¯ãã¾ã«çããããã§ããããè½ã¡ä»ãã¦ã¯ããï¼ãï¼é·ããã¨è çç¶æ ã§ç³ãã¾ã åºã¦ãã¦ããªãã®ã§ï¼è èã«ã¹ããã¯ããã¦ããã¤ãè½ã¡ã¦ãããã¾ãçãã®ãï¼ã¨ãï¼æ¢ã«å°¿ç®¡ã«ãããã¤ã¨ççªãäºæ ãèµ·ãããããã®ãï¼ã¨ãæ°ã«ã¯ãªãï¼ãã1
èªåã¯åã®ä¹¾ããæãé£ãã®ãããããªããã©å ã ãã¾ãæèçç©æ¥µçã«æ°´åãåãç¿æ £ãç¡ã*4ãã¨ãç½ãããã¿ããã§ã¯ããï¼ããã§ãåºç¤¾ãã¦ãããæ¼ã«ãã¯ãå±ã§ãã²ãåºã¦ãã¦ãã飲ãã§ããã¯ãããã©ï¼ãªã¢ã¼ãã«ãªã£ã¦å¤é£ãããã¨ãç¡ãããããããã£ãããå ±ã«ç¡ããªã£ãï¼ä»ã¯æèçã«æ°´ã飲ãããã«ãã¦ã¯ãããï¼ãããããã¨ãã欲æ±ãããããã§ããªããç¿æ £ã«ããªã£ã¦ãªãã®ã§æ°ä»ããã飲ãç¨åº¦ã§ããï¼å®éã®ã¨ããã©ããããã¼ã¹ã§é£²ãã ãããã®ãããããã£ã¦ããªãï¼çæ´»ã®å¤åã«ã¯ããããè½ã¨ãç©´ãããã®ã§ä»å±±ã®ç³ã¨ãã¦æ¬²ããï¼
*1:ä¼ç¤¾ã®phase(人æ°ãäºæ¥)çã«ãéä¸ãããã¨æã£ããç¡éã«ã§ãã¦ãã¾ãç¶æ³ã§ãã£ããã¨ããã
*2:èªåã«ã¯ãã¿ã¼ã³ãè¨æ¶ã§ãã¦ãã¾ããªããã¨ãéè¦ãããæ®éã®æ²ã¨ãã ã¨ãã¾ãã ã£ã
*3:ããã£ã¦ãªãã§ã ãããï¼
*4:ãã¨ãã°é£²ã¿ç©ã¨ãã¦ã³ã¼ãã¼å¥½ããããªãããè¶çãç¿æ £çã«ã¯é£²ã¾ãªãï¼ãã®ããã液æã¿ãããªæ°´åã®å¤ãé£ç©ã¯å¥½ã
singletonsã®åã¬ãã«é¢æ°ã使ã£ã¦ãã¾ãã¨ç¤ºããªãæ§è³ªã®ä¾
âã®è©±
å®ésingletonsãä¹±èãããã ãã©ï¼singletonsããæä¾ããã¦ãåã¬ãã«é¢æ°ã®ä¸ã«ã¯ä½¿ãã¨ããã以ä¸è¨¼æãé²ã¾ãªããªãããã¤ãçµæ§ãªå²åã§å«ã¾ãã¦ã¦ï¼é¢ç½å³ã®ãããªã以åã«æããå è¡ãã¦ãã¾ãï¼ããã¯åã¬ãã«è¨ç®ã®ããã®ã©ã¤ãã©ãªã§ãããªãã¦è¨¼æã®ããã®ã©ã¤ãã©ãªã«ã¯ãªãã¦ãªãï¼ https://t.co/ckCcUpWQLK
— Noriyuki OHKAWA (@notogawa) January 3, 2019
ãµã³ãã«ã³ã¼ãã¯ここ
ãµã³ãã«ã³ã¼ãã§ãããã¨ãã¦ãããã¨ã¯ããªã¹ãã®å転ã¯ãªã¹ãå è¦ç´ ã®ç½®æã®ä¸ç¨®ã§ãããã¨ã示ããã¨ãããã®
ã¾ãï¼2ã¤ã®åã¬ãã«ãªã¹ããç½®æã®é¢ä¿ã«ãããã¨ãå®ç¾©ããï¼
data Permutation :: [k] -> [k] -> Type where PermutationNil :: Permutation '[] '[] PermutationSkip :: Sing a -> Permutation xs ys -> Permutation (a : xs) (a : ys) PermutationSwap :: Sing a -> Sing b -> Permutation (a : b : xs) (b : a : xs) PermutationTrans :: Permutation xs ys -> Permutation ys zs -> Permutation xs zs
å°ããã®å®ç¾©ã«ã¤ãã¦ç¢ºèªãã¦ããï¼å®éã«ã²ã¨ã¤ã®ä¾ã«ã¤ãã¦ç½®æé¢ä¿ã«ãããã¨ç¢ºèªãã¦ã¿ãï¼
testPermutation :: Permutation [1,2,3,4] [2,4,3,1] testPermutation = PermutationTrans (PermutationSwap s1 s2) $ PermutationTrans (PermutationSkip s2 $ PermutationSwap s1 s3) $ PermutationTrans (PermutationSkip s2 $ PermutationSkip s3 $ PermutationSwap s1 s4) $ PermutationSkip s2 $ PermutationSwap s3 s4
ç½®æã¯åå¤é¢ä¿ã®ã²ã¨ã¤ãªã®ã§ï¼åå°å¾ï¼
refl :: Sing xs -> Permutation xs xs refl SNil = PermutationNil refl (SCons x xs) = PermutationSkip x $ refl xs
対称å¾ï¼
sym :: Permutation xs ys -> Permutation ys xs sym PermutationNil = PermutationNil sym (PermutationSkip s p) = PermutationSkip s $ sym p sym (PermutationSwap a b) = PermutationSwap b a sym (PermutationTrans p1 p2) = PermutationTrans (sym p2) (sym p1)
æ¨ç§»å¾ã示ããï¼
trans :: Permutation xs ys -> Permutation ys zs -> Permutation xs zs trans = PermutationTrans
å é ã¸ã®è¦ç´ ã®è¿½å ã¨ï¼éä¸ã¸ã®è¦ç´ ã®è¿½å ã¯ï¼ç½®æé¢ä¿çã«ã¯åããã¨ãæå³ããï¼ã¨ãã£ãæ§è³ªã示ããï¼
here :: Sing a -> Sing xs -> Sing ys -> Permutation (a : xs :++ ys) (xs :++ (a : ys)) here a SNil ys = PermutationSkip a $ refl ys here a (SCons x xs) ys = PermutationTrans (PermutationSwap a x) (PermutationSkip x $ here a xs ys)
ãã¦ï¼å転ãç½®æã®ä¸ç¨®ã§ããã㨠reverseIsPermutation ã¯ï¼
reverseIsPermutation :: Sing xs -> Permutation xs (L.Reverse xs)
ã®ãããªåããã¦ããï¼ãããï¼å®éã«ããã®å®è£ (=証æ)ãä¸ãããã¨ããã¨ï¼
reverseIsPermutation SNil = PermutationNil reverseIsPermutation (SCons x xs) = _
ã¾ã§ããé²ããããªãï¼ãã®typed holeã確èªããã¨ï¼
[-Wtyped-holes] ⢠Found hole: _ :: Permutation (n0 : n1) (Data.Singletons.Prelude.List.Let6989586621679793554Rev (n0 : n1) n1 '[n0])
ã¨ãªã£ã¦ããï¼Let6989586621679793554Revã£ã¦ä½ã¨ï¼singletonsã©ã¤ãã©ãªã®reverseã®å®ç¾©ã確èªããã¨ï¼
$(singletonsOnly [d| (snip.) reverse :: [a] -> [a] reverse l = rev l [] where rev :: [a] -> [a] -> [a] rev [] a = a rev (x:xs) a = rev xs (x:a) (snip.) |])
ã§ããï¼ãã®reverseã®å®ç¾©ããTHã§çæãããReverseã¯exportããã¦ãããï¼reverseå®ç¾©ä¸ã®whereç¯ã«ããrevã¯exportããã¦ããªãã®ã§ï¼ãããæå¾ ããåãç¾ãã¦ãã¾ãã¨è¨¼æãé²ããããã«æ¢ã¾ã£ã¦ãã¾ãï¼
ããã¯ããã©ããããããªãã®ã§ï¼ãããªãèªåã§reverseãå®ç¾©ãã¦è£å©é¢æ°ãåç §ã§ããããã«ããªããã°ãªããªãï¼
$(singletonsOnly [d| myReverse :: [a] -> [a] myReverse l = myReverseAcc l [] myReverseAcc :: [a] -> [a] -> [a] myReverseAcc [] ys = ys myReverseAcc (x:xs) ys = myReverseAcc xs (x:ys) |])
ãã®myReverseã®å®ç¾©ããçæããã MyReverse ã MyReverseAcc ã«ããï¼åæ§ã«å転ãç½®æã§ãããã¨ã示ãã¨
myReverseIsPermutation :: Sing xs -> Permutation xs (MyReverse xs) myReverseIsPermutation xs' = gcastWith (nilIsRightIdentityOfAppend xs') (go xs' SNil) where go :: Sing xs -> Sing ys -> Permutation (xs :++ ys) (MyReverseAcc xs ys) go SNil ys = refl ys go (SCons x xs) ys = PermutationTrans (here x xs ys) (go xs (SCons x ys))
ã®ããã«ç¤ºããã¨ãã§ããï¼nilIsRightIdentityOfAppend 㯠[] ããªã¹ãçµåæ¼ç®ã«å¯¾ããå³åä½å ã§ãããã¨ã示ãã¦ããï¼
nilIsRightIdentityOfAppend :: Sing xs -> (xs :++ '[]) :~: xs nilIsRightIdentityOfAppend SNil = Refl nilIsRightIdentityOfAppend (SCons _ xs) = gcastWith (nilIsRightIdentityOfAppend xs) Refl
ã¨ãã£ãããã«ï¼singletonsã®Singã®å®ç¾©ã¯å¥æ®µåé¡ç¡ããï¼Data.Singletons.Prelude 以ä¸ã®ã¢ã¸ã¥ã¼ã«ã§å®ç¾©ããã¦ããåã¬ãã«é¢æ°ã使ã£ãã¤ã³ã¿ã¼ãã§ã¼ã¹ã¯ï¼ããã ãã§è¨¼æãã§ããªããªã£ã¦ãã¾ããããªãã®ãå¤æ°åå¨ãã¦ããï¼whereãletãªã©ã®è£å©é¢æ°ã«ããå®ç¾©ããã¦ãããã®ã¯æããå ¨æ» ãããªãã ãããï¼ãªã®ã§ï¼ãããã£ããã®ãã©ã¤ãã©ãªå¤ã«exportããå ´åã¯ï¼ãã®ã¾ã¾singletonsã®ãã®ã使ãã®ã§ã¯ãªãé©å®hideããä¸ã§ï¼èªåã§å®ç¾©ãã証æå¯è½ãªãã®ã§ä»£æ¿ãã¦exportããã»ãã親åãããªãããªã¨ï¼
cerealã®getFloat*å¤ç¨ã¯ã¡ã¢ãªé·è ã«ã®ã¿è¨±ãããè´ æ²¢
ç´1å¹´ãæ¸ãã¦ãªãã£ãã®ãï¼
ãã2,3å¹´ã¯ããããã®ãµã¤ãºã®é åãã©ãããããæ©ä¼ãå¤ãï¼ããããã¨ãç¹ã«ä½ãèããªããã° Data.Vector ã«çªã£è¾¼ãã§ãããããã¢ãã«ãªãï¼ã§ï¼å®éã«å¤§ããªé åãHaskellã§æ±ãã¨ã¡ã¢ãªä¸è¶³ã§OOM Killerã«æ®ºããããããããã ãã©ï¼ãããªåå ã®ã²ã¨ã¤ã«ã¤ãã¦ï¼
ãµã³ãã«ã³ã¼ãã¯ココã«ããã®ã§ãããªäººã¯ã©ããï¼
stack init stack build
ã¾ãputterã¨ããexecutableããããã大ããªè¦ç´ æ°ãæã£ãFloatã®é åãlittle endianã§åºåããï¼
stack exec putter
ããã§ã«ã¬ã³ããã£ã¬ã¯ããªã«output.dat ã¨ãã50MBãããã®ãã¡ã¤ã«ãã§ãããã¨ï¼æ¬¡ã«naive-getterã¨ããexecutableã§output.datãèªã¿åºãï¼ãã£ã¦ãããã¨ã¯ï¼Floatã®é åã«æ»ãã¦ç·åãåãï¼å ã®é åã®ç·åã¨ä¸è´ããããè¦ã¦ããã ãï¼
stack exec naive-getter
naive-getterã®å®è£ ã§ByteStringããFloatã®Vectorã«変換する部分ã¯ï¼æ¬¡ã®éãcerealã§getFloat32leã使ã£ãè³ç´å®è£ ã«ãªã£ã¦ããï¼èªç¶
runGetLazy (V.replicateM len getFloat32le) dat
ãããï¼ã³ã¤ããæ³å以ä¸ã«ã¡ã¢ãªããã«é£ãããã®ã§ï¼é©å½ã«ãããã¡ã¤ã«ãè¦ã¦ã¿ãï¼
stack build --profile stack exec -- naive-getter +RTS -hc -p -s stack exec -- hp2ps -c naive-getter.hp open naive-getter.ps
ããã¨ãããªæãã«ãªãï¼ãããï¼
8ç§ã¡ããã¾ã§ã¯putterãåºããé åãgetterã§ãå度ä½ã£ã¦ç·åã¨ãè©ä¾¡ãã¦ãé¨åãªã®ã§ç¡è¦ããã¨ãã¦ï¼Unboxed Vectorã§ã¯ãªããã¨ãèæ ®ãã¦ã以éã®ã¡ã¢ãªæ¶è²»ã¯ç«ã¡ä¸ããéãã¦ããï¼ã©ããããã¨ãã¨getFloat32leの実装ãè¦ã«è¡ãã¨ï¼æ¬¡ã®ããã«ãªã£ã¦ããï¼
-- | Read a Float in little endian IEEE-754 format getFloat32le :: Get Float getFloat32le = wordToFloat <$> getWord32le (snip.) {-# INLINE wordToFloat #-} wordToFloat :: Word32 -> Float wordToFloat w = unsafeDupablePerformIO $ alloca $ \(ptr :: Ptr Word32) -> do poke ptr w peek (castPtr ptr)
1è¦ç´ æ¯ã«ã³ã¬ããããã ãï¼é åã®ãããªã³ã¬ã¯ã·ã§ã³ä¸ã®è¦ç´ ãä¸æ°ã«ããããå¤æãããªãéã«次のような関数ã§ããããªã¨å¥ã®æ段ãç¨æããï¼
getFloat32leVector :: Int -> Get (V.Vector Float) getFloat32leVector n = do v <- V.replicateM n getWord32le return $ unsafeDupablePerformIO $ alloca $ \ptr -> do V.mapM (\x -> poke ptr x >> peek (castPtr ptr)) v
ããã§getFloat32leãç½®ãæãã¦次のように使ったrevised-getterãä½ãï¼
runGetLazy (getFloat32leVector len)
ãã¡ãã§ãnaive-getteråæ§ã«profileãåãï¼
stack build --profile stack exec -- revised-getter +RTS -hc -p -s stack exec -- hp2ps -c revised-getter.hp open revised-getter.ps
çµæã¯ã ãã¶æ¸ã£ããã¨ããããï¼ããã§ãã¾ã 大å¯è±ªæ§ã§ã¯ããããã ã
å¥ã«ç·åãããã ã£ããã¹ããªã¼ã å¦çãã°ãããã ãããã©ããã¯ç°¡åã®ããã«ç·åãç½®ãã¦ãã ãã§ï¼ç¾å®çã«ã¯ãã£ã¨é åå ¨ä½ãã¬ãã£ã¬ãã£ããå¦çãæ§ãã¦ããããããããããã«ãï¼
Deep Learning Accelerationåå¼·ä¼ ã§çºè¡¨ãã¦ãã¾ãã
Deep Learning Acceleration勉強会 - connpass ã«ã¦ã¹ã©ã¤ãã¯ãã¡ã
www.slideshare.net
æ®æ®µã¯åºã¦ãé¢æ°åè¨èªããå½¢å¼ææ³ããã®åå¼·ä¼ã¨ããªããï¼ã¢ã¦ã§ã¼æã«ããã½ã¯ã½ã¯ãã¦ããï¼ãªãããã®çºè¡¨ã§ä½ã¬ã¤ã¤ãã³ã¨æãããå¯è½æ§ããããã©ããã§ã¦ãã«ãªããã«è¾¿ãä»ããã¦ãã¹ã¤ãã»ã³ãã®ããã°ã®ä»ã®è¨äºã§ããããããã«è¶ é«ç´è¨èªä½¿ãã§ãã¨ããè¨ããªãï¼
æã£ã以ä¸ã«æ§ã ãªã¬ã¤ã¤ã¼ã«é¢ããçºè¡¨ãããã©ããã«ãªã«ãªã«ãããã¨ããã¨ã¬ã³ããªã ããã¨ï¼ããããè¨ç®æ©ç§å¦ã®å ¨ã¦ã®ã¬ã¤ã¤ã¼ã«ç²¾éãã¨ãã«ãªã£ã¡ããããªã¿ãããªãã³ãããããªã£ã¦ããã¨ããããã§ã¯ãªãï¼çéã§ãããããã¤ã ã¨FPGAã«ã¤ãã¦ã®è©±ãç¡ãã£ãã®ã§æ¬¡ããããªãFPGAå¢ã®é²æã¯èãã¦ã¿ããï¼
å人çã«ã¯ç§èããã«ããã®è¨äºã®è ã§ããã¨æ¨æ¶ã§ããã®ã§ããã£ãï¼ã(ã²ã¨ã¤åã®è¨äº)ã«ã¤ãã¦ä¸å¿«ã«ãããããã§ç³ã訳ãªãï¼ä»ã®Unagiã®æ¹ã ã«ããããããããããã¾ãï¼ãã¨ï¼æ°ã®çºè¡¨ã§ãèªå·±ç´¹ä»ã§Kagglerã§ããã¨ããã¨ããã§ãæ段ãé¸ã°ãåã¡ã«ããã¾ããã¨è¨ã£ã¦ã¦ããæ°æ¥ã®æµããè¸ã¾ãã¦ã®ã»ãªããã§ã¤ã¹ãã¦ãããã®ããªã¼ã¨æã£ã¦é¢ç½ãã£ãï¼
æ¢ã«ãã¥ã®ã£ããã¦ãã®ã§ãã¡ããåè
ICFP Programming Contest ãæ¬å½ã«ç¸ã£ã¦ãããã®
以åï¼ããæ°å¹´ã®ICFP Programming Contestã«ã¤ãã¦æã£ã¦ãããã¨ã«ã¤ãã¦ã®ãã¤ã¼ã(群ã®ä¸é¨)ãï¼ Rustが最強のプログラミング言語である証明 — hayato.io ã§åãä¸ãããããï¼ @chokudai ããã«å±ãã¦åå¿ãã¦ãããããã§ããããï¼ä¸é£ã®æ°ã®ãã¤ã¼ããRTããå¾ï¼æããï¼
ï¾ï½¯ï½ºï¾
— Noriyuki OHKAWA (@notogawa) 2017å¹´9æ1æ¥
ä¸ç¹ï¼ãã¤ãã¿ã¼ã ã¨åå¾ã®æèã¶ãã¯ãªè½ã¡ããã¨ãããããä»æ¹ãªããã ãã©ï¼æ£ããä¼ãã£ã¦ãã®ãæ°ã«ãªã£ãã®ãï¼ãç¸ããã®æ¬è³ªã«ã¤ãã¦ï¼
ãããããè¨èªãä¸ã¤ã«çµ±ä¸ããç¸ããã¬ã¤ãã¿ãããªãã¨è¨ã人ãããã©ãåä¼ç¤¾ããã®ãããã¯ãã§ä½¿ç¨è¨èªãçµ±ä¸ãã¦ããã®ã¯ãããã§ãããããã§ãä½ï¼ããããã®ç¸ããã¬ã¤ã ã¨æã£ã¦ãã®ï¼ã¨æããããè¶ å¤è¨èªéçºã§ã3æ¥éã§å½¢ã«åºæ¥ããã£ã¦ã®ãç¥ããããã®ã¯ååé¢ç½ãã¨æãã®ã ãã©ã
— chokudai(é«æ© ç´å¤§) (@chokudai) 2017å¹´9æ1æ¥
ããã¤ã¯åå ãããã©æ¨ãè¨èªãéãããçµããªããã ããªã¼ã¿ãããªã®ããã£ã¦èªç¶ã¨ãã¼ã 人æ°ãçµããã¦ãç¯ããã£ãã¨æããã ãã
— Noriyuki OHKAWA (@notogawa) 2017å¹´8æ4æ¥
åãä¸ãããããã¤ã¼ãã®ç´å¾ã®ãã®ãã¤ã¼ãããããããããã«ï¼ååã¨ããåºå®ã¡ã³ãã¼ã¨ãããã¨ã決ã¾ã£ã¦ããªã·ã´ãã¨ã¯ç°ãªããã¼ã çµã¿ããã§ããã³ã³ãã¹ãã§ãï¼æ¨ãè¨èªã®å·®ãå¼·ãå¶ç´ã¨èªèããå ´åããããå¼·ããã¨ãããã£ã¦ã¦ãå®æãéãããçµããªã奴ãåºã¦ããããã¨ããããã®ã³ã³ãã¹ãã«ãããéè¦ãªãç¸ããã§ããï¼ä½ããè¨èªãä¸ã¤ãã使ããªããã¨ãããç¸ããã®æ¬è³ªã§ã¯ãªãã¨æã£ã¦ããï¼
ããã¯ï¼ãã®ã¨ãã®æµãã®ä¸ã§ @mametter ããã¨ã®ããã¨ãã§ãï¼
ãã®æ¹å¤ã«å¯¾ãã¦ã¯ï¼é¸æããã1,2è¨èªã ãèªå®ãã¦ããæãªããè¨èªãè¯ãããããåªç§ãªããã°ã©ããé äºãå¼ãä»ãããã ãã¨ããåè«ããã£ããã§ããï¼5ï½6è¨èªãæå¼·è¨èªã«é£ãããã¨ã許ãã¦ãã¾ã£ãã®ã§åè«ã使ããªããªã£ã¦ãã¾ãï¼ä»ã¯æ£ã«æ¹å¤ã®éãã«ãªã£ã¦ãã¨æãã¾ãï¼
— Noriyuki OHKAWA (@notogawa) 2017å¹´8æ6æ¥
ã¨ã«ããå¼·ã奴ã§éããããå¼·ããï¼ã¨ãããã¨ã ã£ããæ¬å½ã«ãã³ãã¢ã¢ãªãªä»ã®ã³ã³ãã¹ãã ããããããããªã·ã´ãã»ç¾å®ä¸çã§ãã¿ããªããã£ã¦ããï¼
åã¡ã«è¡ãã®ãã³ã³ãã¹ãã«åå ããä¸ã§ãããã¾ãã®ãã¨ã ãï¼ã«ã¼ã«ãä½ããã®ç¹ã«ã¤ãã¦ç¸ã£ã¦ãããã§ã¯ãªãã®ã§ãã³ãã¢ã¢ãªãªã³ã³ãã¹ãã¨å½¢å¼ã¯åããªãã ãã©ï¼æè§ ICFP Programming Contest ãªããçµããªã奴ãåºã¦ãããã¨ããç¹å¾´ãæããã°ããããããªãããªã¨ããã®ãç§è¦ï¼
ã¾ãï¼
æ®å¿µæã¯ããããã ãã©ããããåä¸ã®æå¼·è¨èªèªå®ã¨ããèãæ¹ã®ã»ããç¾ä»£ã®ããã°ã©ãã³ã°ã«å³ãã¦ããªããã¨ããæè¦ãå»å¹´ã®éå¶ãã¼ã ã§åºã¦ããªãã
— Yusuke Endoh (@mametter) 2017å¹´8æ6æ¥
ã¨ãã話ãããã®ã§ï¼ ICFP Programming Contest ãä»ã®ã³ã³ãã¹ãã¨ä»ã¯ããä½ãå¤ãããªãã®ãããããªãï¼ãã¶ãä¼¼ããããªãã¨ãæãã¦ãã®ã¯ä»ã«ã @shinh ããã¨ãããããªã®ããªï¼
ããã¤ã¾ãã¦ãã®æ¹å¤ã ã¨æã£ã¦ãã¦(ä»ã«ããããªããã¾ãããã©)ã https://t.co/VSuSYWkPdv ãã³ãããã§æ¸ãã¦ãã½ãæ®´ããããã£ã¦ã»ãããã ããªã https://t.co/htHLHiwV8j
— shinichiro hamaji (@shinh) 2017å¹´8æ4æ¥
ãããã«ãããã£ããã°ããâ¦ãªã®â¦ã§ã¯ï¼ãçµããªã奴ãåºã¦ãããã¨æã£ã¦ãã®ãæãè¾¼ã¿ã ã£ãã®ãããããªãï¼æåãã ICFP Programming Contest ã¯è¨èªãªãã¦ã©ãã§ãããã£ãã®ãããããªãï¼
ãã¡ããç¦æ¢ã§ã¯ãªãããã ãããªãã§ãããå¢ã«ç¸ããã¬ã¤ã§åã¤ã£ã¦ã®ãæé«ã«ãã³ã¤ã¤ã£ã¦é¢ãããããå¥ã«ã©ãã§ããããã ãã©
— Noriyuki OHKAWA (@notogawa) 2017å¹´8æ4æ¥
ã¨ããããã§çµè«ã¨ãã¦ã¯æçµçã«ã©ãã§ããã話ã§ããã¨ããæã«è½ã¡çãï¼
ãã ï¼ @chokudai ããã¯èªããã³ã³ãã¹ã(ãµã¤ã)ãéå¶ããè ã¨ãã¦ï¼ä»ã®ã³ã³ãã¹ã(ã ããããªãä½ããã®ã³ãã¥ããã£ãæåã«)ä¹ãè¾¼ãå ´åï¼åã¡ã ããããªãã¦ãããã¯ä½ãç®çã«ãã¦éå¬ããã¦ããã®ããã«ã¤ãã¦ã®ãã ããã«å¯¾ãï¼åã«å¼·ããæ¯ãåãå½¼ã®ãã¤ã¼ãã«ããè¨èãåãããªãã°ãæ°´å·®ãããã¨ããªãããå¤å°æããå·¡ããã¦æ¬²ããããªã¨æãé¨åãããï¼èªåã¯å½¼ã®ã¤ããããã¤ã¡ã¿ãããªãã¤ã¼ãã好ãã ãå®éãã以ä¸ã«ã¤ããï¼åãªãåã¡ã ãã«ãã ãããï¼ãããã£ãé¨åããªã¹ãã¯ãããä¸ã§ãªãåã¤åãå½¼ã«ã¯ååããã¨æã£ã¦ããï¼
ä¸æ¹ï¼å½¼ã®å ´åã³ã³ãã¹ãã§èº«ãç«ã¦ãã®ããªã·ã´ããªé¨åãããï¼ã¿ããªããã©ã¤ãã¼ãã¨ãã¦åå ããã³ã³ãã¹ãã§ãã£ã¦ãå½¼ã«ã¨ã£ã¦ã¯å®£ä¼ã»åºå ±ãå«ãã åæ¥çãªæå³ãã¡ã¤ã³ã§ã¯ãªãã«ããæããããå¾ãªããï¼å¨å²ãããæããã¨èããã®ãèªç¶ã ããï¼å½¼ã®äºæ¥æ§è³ªä¸ã¯å¼·ãã¡ã³ãã¼éãã¦åã£ã¦ãã©ã³ãã£ã³ã°ã»ã¢ãã¼ã«ããã¨ããã®ã¯ã¡ã³ãã¼ãéããä¸ã§ãå¹æãããæ£çã ï¼å½¼èªèº«ãã³ã³ãã¹ãå¼·ãã¦æåããã¢ãã«ã±ã¼ã¹ã«ãªããªããã°ãªããªãã®ã ããï¼ã ã¨ãããèããã«ãè¦ãããããªçãã ã¼ãããªã¼ãã£ã¨ã³ã¹ã«è¦ããããã«ããããªãã ãããï¼ã¾ãã¦ãããã§è² ããã®ããã¤ãã¹ã§ã¯ãªãã«ããæ©æ¢°æ失çãªãã®ã¯ãããããããªãï¼ãã®ãããã®ç«å ´ãèæ ®ããã¨åã«ã³ã³ãã¹ãã«åå ããã ãã«ãã¦ãä»ã®åå è ã«ã¯ãªãæå¾ ãèè² ã£ã¦ããããªã¹ã¯ãåã£ã¦ããé¨åããã大å¤ã ãããªãã¨åæã«å¿é ãã¦ããï¼
ãããããä½ã«æ°ãä»ãã¦ããã°ã£ã¦é ãããï¼
TensorFlowã§è¨ç·´ãããã©ã¡ã¼ã¿ãChainerã®ã¢ãã«ã«restoreãã
ä½ãã©ããªã£ã¦ã深層å¦ç¿ãçãªãã®ã«è§¦ããæ©ä¼ãå¢ããã®ã§ï¼ä½ãããã£ã½ã話ã
ãä»ã®ãã¬ã¼ã ã¯ã¼ã¯ã«æ¯ã¹ã¦ãªãã ãå¦ç¿æ¸ã¿(pre-trained)ã¢ãã«ãå ¬éããã¦ãªããããªï¼ã
Chainerã使ã£ã¦ã¿ã深層å¦ç¿ãã³ã¯ãã£ã¨ãã®ãæ°æã¡ã«ãªã£ããã¨ãããããããªãã ãããï¼ã¦ã¼ã¶æ°ã®å·®ã ãããï¼æ°ã¯åã ãå è²´ï¼Caffeã®ã¢ãã«ãã¡ã¤ã«(.caffemodel)ã§ããã°ï¼ãã®ã«ãã£ã¦ã¯chainer.links.caffe.CaffeFunctionã§ãã¼ãã§ããã®ã§ä¸å¿ä½¿ãã¯ããï¼global pooling çã§é対å¿ããããã¼ãã§ããªããã¨ããããï¼ã§ããªãé¨åã¯é£ã°ãã¦ãã¼ããã¦ã¹ãããèªåã§æ¸ãã¦ãã¨ãã§ããªãã¯ãªãã®ã§ï¼ã¹ã³ããªã¨ãã¼ãã¯ã§ããªãã¨ãã¬ã³ããªã§ãã¼ãã¯ã§ããæ°ãããï¼
ä¸æ¹ï¼ãªãã ããã TensorFlowã®pre-trainedã¢ãã«ãckptãã¡ã¤ã«ã§å ¬éããã¦ãããã¨ã¯å¤ãï¼
ããã¤ãããChainerããå©ç¨ãããã¨ãªã£ã¦ãããã¾ãè¨äºã¨ããè¦å½ãããªãï¼ã¾ãéã«ã¤ãã¦ãç¡ãã¨ãããï¼ãããã¬ã¼ã ã¯ã¼ã¯ãè¶ãã¦ã©ãã«ããã話ãããã¾ããªãï¼ã©ãã«ããããã¨ããé°å²æ°ãåãã¯æ£è¦ããããã©ï¼å ¨ä½ããã¿ããã¾ã äºã®æ¬¡æ¡ä»¶ã®ããã«è¦ããï¼ããè¨ç·´ããã深層å¦ç¿ãã³ã«ã¯ãããªãã¨å¼å¸ã«çããã¿ã¹ã¯ã ãããªã®ãï¼ããã¨ãããã¾ããããã£ãããã¯ããªããããªã®ãï¼ãããã¯ï¼ãããªãã¨ããã§ãè¨ç®è³æºããããã¾ã£ã¦ã¦æ°è¦ã«å¦ç¿ãã¡ããã°ããã ãã¨ãããã¨ãªã®ãï¼
ãããã«ããï¼ãã®ã¢ãã«ãChainerã§æ¸ãã¦ã¿ãã¡ãã£ã¨ã¡ããã¨åãã試ãããâ¦ãã©å¦ç¿æ¸ã¿ã®ãã®ã¯ç¡ãã¦ãç¨åº¦ã®ãã¨ã§ï¼æè¿ãã®æ±äº¬å¤§å¦ã§ããç¯ç´ãã¦ããã¨åã®è²´éãªè²´éãªé»å(ã¨æé)ãæ¶è²»ãã¦æ°è¦ã«å¦ç¿ãå§ããã¨ããã®ãå¿è¦ããï¼Gentoo使ããªããããã ï¼ãªã®ã§ï¼ãã£ã±ãã¯ãã¹ãã¬ã¼ã ã¯ã¼ã¯ã§ãåå©ç¨ãããã¨ããã®ã¯ããããããªãããªã¨ï¼
ã¨ããããã§ckptãã¡ã¤ã«(群)ã®ãã©ã¡ã¼ã¿ãChainerã®ã¢ãã«ã«restoreããæ¹æ³ã¯ï¼
- ckptãã¡ã¤ã«(pre-trainedãªã¢ãã«)ãå ¥æ
- ãã®ckptãã¡ã¤ã«ãå¦ç¿ããTensorFlowã®ã¢ãã«ãå ¥æ
- TensorFlowã®ã¢ãã«ãçºãã¦åãã©ã¡ã¼ã¿ã«ä»ããããå称ã調ã¹ã
- TensorFlowã®ã¢ãã«ã¨åãã¢ãã«ãChainerã§æ¸ã
- TensorFlowã®CheckpointReaderã§ckptãã¡ã¤ã«ãéã
- ckptãã¡ã¤ã«ããåå称ã®ãã©ã¡ã¼ã¿ãå¼ã£å¼µãåºã
- TensorFlowã¨Chainerã§ã¯weightã®dimã®é çªãéãã®ã§å¿ è¦ã«å¿ãã¦è»¢ç½®
- chainer.Linkã®å¯¾å¿ãããã©ã¡ã¼ã¿ã«ä»£å ¥ãã¦ãã
ã¿ãããªæµãã«ãªãï¼
class CKPT: def __init__(self, path): # ckptãã¡ã¤ã«ãéã self.ckpt = tf.train.NewCheckpointReader(path) # ndimè¦ã¦æ±ºãæã£ã¦ããã©ï¼ãã®ãã©ãä½ã®ãã®ãã¯ã¢ãã«ããããã£ã¦ãã®ã§ï¼ # æ¬å½ã¯åå¥ã«get_conv2d_weightã¨ãget_fc_weightã¨ããç¨æããã»ãããã def get(self, name): arr = self.ckpt.get_tensor(name) nd = np.ndim(arr) # å¿ è¦ã«å¿ãã¦è»¢ç½® if nd == 4: # ãããã 2D Convolution ã ãã㨠return arr.transpose(3,2,0,1).copy() # TensorFlow -> Chainer if nd == 2: # ãããã Fully Connected ã ãã㨠return arr.transpose(1,0).copy() # TensorFlow -> Chainer if nd == 1: # biasãBatchNormã®ãã©ã¡ã¼ã¿ã ãã㨠return arr else: pass # unknown weight type # TODO: raise Exception (snip.) # Chainerçã®ã¢ãã« class YourModel(chainer.Chain): def __init__(self): super(YourModel, self).__init__( c0 = L.Convolution2D(3 , 16, 7, 3, 3, nobias=True), bn = L.BatchNormalization(16, 0.9997, 0.001) c1 = L.Convolution2D(None, 32, 3, 1, 1), (snip.) ) def __call__(self, x): (snip.) def restore_from_ckpt(self, path): ckpt = CKPT(path) # åå称ã®ãã©ã¡ã¼ã¿ãå¼ã£å¼µãåºã self.c0.W.data = ckpt.get('PreTrainedModel/Conv2d_0/weights') self.bn.beta.data = ckpt.get('PreTrainedModel/BatchNorm/beta') self.bn.gamma.data = ckpt.get('PreTrainedModel/BatchNorm/gamma') self.bn.avg_mean.data = ckpt.get('PreTrainedModel/BatchNorm/moving_mean') self.bn.avg_var.data = ckpt.get('PreTrainedModel/BatchNorm/moving_variance') self.c1.W.data = ckpt.get('PreTrainedModel/Conv2d_1/weights') self.c1.b.data = ckpt.get('PreTrainedModel/Conv2d_1/bias') (snip.) if __name__ == '__main__': model = YourModel() model.restore_from_ckpt('pre-trained.ckpt') (snip.)
ãã¡ããï¼ããã§ä¸äºãã¾ãããã¨ããããã§ã¯ãªãã ãããï¼
åå調ã¹ãã®ããã©ããããªãã¨ããå ´åï¼CheckpointReaderã®get_variable_to_shape_mapã§shapeã¨å ±ã«ä¸è¦§ã§ããã®ã§ï¼ããè¦ã¦å¤æã¨ãã§ãã§ããªãã¯ãªããã¨ãããï¼