åé¡ã解決ããã¤ããã§ããããªåãä»ããå ã«ããé«ãå£
nullå®å ¨ããããã«ãªããããããããããè¦ãã¤ãã¾ã¤ã æ©æ¢°ãç解ã§ããè¤éãªå¥ç´ã®å表ç¾ããããããã®ã¯ ã¤ã¾ãã¨ãããã®ãããªãã® ãã¶ã¶(åã£ãè ¹ãã証æãªãã¸ã§ã¯ããå¼ãæºãåºã)
— Noriyuki OHKAWA (@notogawa) 2016å¹´11æ18æ¥
éãããã¯ç¶åã°ããããã¨ãï¼
æè¿nullå®å ¨ï¼ã ãã®è©±ã®ããã¿ã§ï¼(éçãª)åã§å¥ç´äºã ã表ç¾ãã¦ã·ã¢ã¯ã»ã«ãªãããã ãã¼ã¨è¨ãã®ããã©ãã©è¦èãããï¼ãã¨ãã°ï¼pythonã§çµ±è¨ãªãæ©æ¢°å¦ç¿ãªããã£ã¦ã¦numpyå¼ããããªäººãï¼ndarray(多次元配列)ã®shape(多次元配列の形)ãåããã¨ã©ã¼ã§è½ã¡ããã¨ãããããã¢ã¬ã«ã¤ãã¦äºã ã¨ããï¼ãªãã»ã©åãããã°å®è¡åã«æ¢ãããã¨ãã§ãï¼å®è¡æï¼ã¨ã©ã¼*1ã«ãªã£ã¦ãã¡ã¼ã¿ãããªãã¨ã¯é¿ããããã ããï¼
ãããï¼ããã天å½ã¸ç¶ãéãã©ããã¯ã¾ãå¥ã®è©±ï¼(ä¾å)åã§èè£ ãã¦ããã®ã¯å°çã¸ã®éãããããªãã®ã ï¼åé ãã¤ã¼ãã®éãé°è ¹å¬ãã¦ã§ãè««ãã¦ãããã°ï¼ãã®å¸æï¼å®¹æã«çµ¶æã«å転ãå¾ãï¼
ã§ã¯å®éã«è¦ã¦ãããï¼å 容ã¨ãã¦ã¯ï¼numpy ndarrayã¨ãã®ä¸ã§ã®æä½ãããã¤ãåãä¸ãï¼é åè¦ç´ ã ãã§ãªãshapeã¾ã§åã¬ãã«ã§æ±ããã¨ã§ï¼ééããshapeãæã¤æä½ãç¦æ¢ã§ããããã«ãã¦ã¿ãã¨ãããã®ï¼ãµã³ãã«ã³ã¼ãã¯コチラï¼å ¨ä½ã®æµãã¨ãã¦ã¯ndarrayãå®ç¾©ï¼reshapeï¼dotï¼transposeãå®è£ ï¼ãããã使ã£ã¦tensordotãå®è£ ãã¦ã¿ãã¨ã©ããªãããã¿ã¦ããï¼
前回の記事ã«ç¶ãï¼ä»åãåã¬ãã«ã§ã¢ã¬ã³ã¬ããã®ã§ã¢ã¿ãã®ã»ãã¯ãããªæãï¼singletonsã使ã£ã¦ããï¼
{-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE DataKinds #-} import Data.Singletons import Data.Singletons.Prelude.Enum import Data.Singletons.Prelude.List import Data.Singletons.Prelude.Num import GHC.TypeLits
shapeã¨ä¸èº«ã®åaãåã¬ãã«ã«æã¤NDArrayåãå®ç¾©ããï¼ä»åã¯ä¸èº«ã®è¨ç®ã«ã¯èå³ãç¡ãã®ã§ï¼shapeã«é¢ããæ å ±ã ãæ±ãã¦ãããã¨ã«ããï¼
data NDArray (shape :: [Nat]) a = NDArray (Sing shape) -- ä¸èº«ã¯shapeæå¤çç¥
ã¾ãã¯ï¼numpy.reshapeãå®è£ ãã¦ã¿ãï¼
reshape :: Product from ~ Product to => Sing to -> NDArray from a -> NDArray to a reshape = const . NDArray
è¦ç´ æ°ãåãã§shapeã®éãå¥ã®ndarrayã«å¤æããæä½ã ãï¼å¥æ®µä¸å¯æè°ãªã¨ããã¯ç¡ãï¼ã³ã³ããã¹ãé¨åã«ããè¦ç´ æ°ãåãã¨ããæ¡ä»¶ãä»ãã¦ããï¼ä»¥ä¸ã®ããã«ç¢ºãã«æ¡ä»¶ã«åããªãå ´åã¯åæ¤æ»ã§å¤±æããï¼
-- reshapeå¯ reshapeable :: NDArray '[2,3,4] a -> NDArray '[3,8] a reshapeable = reshape sing -- åæ¤æ»ã§reshapeä¸å¯ (次å ã®ç©ãåããªã) -- unreshapeable :: NDArray '[2,3,4] a -> NDArray '[3,3,4] a -- unreshapeable = reshape sing -- Couldn't match type â24â with â36â
次ã«ï¼numpy.dotãå®è£ ããï¼
dot :: (Last xs ~ Last (Init ys), Num a) => NDArray xs a -> NDArray ys a -> NDArray (Init xs :++ Init (Init ys) :++ '[Last ys]) a NDArray xs `dot` NDArray ys = NDArray (sInit xs %:++ sInit (sInit ys) %:++ SCons (sLast ys) SNil)
dotç©ãåã2ã¤ã®ndarrayã®shapeããçµæã®shapeã決å®ããï¼1ã¤ç®ã®shapeæå¾ã®è¦ç´ ã¨ï¼2ã¤ç®ã®shapeæå¾ãã2çªç®ã®è¦ç´ ãåãã¨ããæ¡ä»¶ãä»ãã¦ããï¼ãããï¼ä»¥ä¸ã®ããã«æ¡ä»¶ã«åããªãå ´åã¨çµæã®åãåããªãå ´åã¯åæ¤æ»ã§å¤±æããï¼
-- dotå¯ dottable :: Num a => NDArray '[2,3,4] a -> NDArray '[3,4,2] a -> NDArray '[2,3,3,2] a dottable = dot -- åæ¤æ»ã§dotä¸å¯ (çµæã®åãåããªã) -- undottable1 :: Num a => NDArray '[2,3,4] a -> NDArray '[3,4,4] a -> NDArray '[2,3,3,2] a -- undottable1 = dot -- Couldn't match type â4â with â2â -- åæ¤æ»ã§dotä¸å¯ (å¼æ°ã®åãåããªã) -- undottable2 :: Num a => NDArray '[2,3,4] a -> NDArray '[4,3,2] a -> NDArray '[2,3,4,2] a -- undottable2 = dot -- Couldn't match type â4â with â3â
æå¾ã«ï¼numpy.transposeãå®è£ ããï¼
transpose :: Sort axes ~ EnumFromTo 0 (Length shape - 1) => Sing axes -> NDArray shape a -> NDArray (Map ((:!!$$) shape) axes) a transpose axes (NDArray shape) = NDArray (sMap (singFun1 (toProxy shape) (shape %:!!)) axes) where toProxy :: Sing (shape :: [Nat]) -> Proxy (Apply (:!!$) shape) toProxy _ = Proxy
æ¡ä»¶ã¯å°ãè¤éã«ãªãï¼è»¸(次å )ã®è»¢ç½®æ¹æ³ã«ç¸å½ãããã©ã¡ã¼ã¿axesãï¼ã¡ããã¨shapeå ¨ä½ã®permutationãæå³ãããã©ã¡ã¼ã¿ã«ãªã£ã¦ããªããã°ãªããªãï¼ãããï¼æ¬¡ã®ããã«åçç±ã§æ´åããªãå ´åã¯åæ¤æ»ã§å¤±æããï¼
transposable :: Sing '[1,0,2] -> NDArray '[2,3,4] a -> NDArray '[3,2,4] a transposable = transpose -- transposeä¸å¯ (axesã«shapeã®é·ã以ä¸ã®ãã®ãå«ã¾ãã) -- untransposable1 :: Sing '[1,0,3] -> NDArray '[2,3,4] a -> NDArray '[3,2,4] a -- untransposable1 = transpose -- Couldn't match type â3â with â2â -- transposeä¸å¯ (axesã«åãè¦ç´ ã2ã¤ä»¥ä¸å«ã¾ãã) -- untransposable2 :: Sing '[1,0,0] -> NDArray '[2,3,4] a -> NDArray '[3,2,2] a -- untransposable2 = transpose -- Couldn't match type â1â with â2â -- transposeä¸å¯ (axesã®é·ãã¨shapeã®é·ããä¸è´ããªã) -- untransposable3 :: Sing '[1,0] -> NDArray '[2,3,4] a -> NDArray '[3,2] a -- untransposable3 = transpose -- Couldn't match type â'[]â with â'[2]â -- transposeä¸å¯ (çµæã®åãåããªã) -- untransposable4 :: Sing '[1,0,2] -> NDArray '[2,3,4] a -> NDArray '[3,2,5] a -- untransposable4 = transpose -- Couldn't match type â4â with â5â
ãã¦ï¼reshape,dot,transposeãå®ç¾©ãããã®ã§ï¼ãããã使ã£ã¦numpy.tensordotãå®ç¾©ã§ããï¼ã¯ãã§ããï¼å®éã«ãããããã°ãããããã¨ããæè¦ã«å¾ã£ã¦å®è£ ãã¦ã¿ããï¼
tensordot :: (Num a, ns ~ Nub ns, ms ~ Nub ms, Map ((:!!$$) xs) ns ~ Map ((:!!$$) ys) ms) => NDArray xs a -> NDArray ys a -> (Sing ns, Sing ms) -> NDArray (Map ((:!!$$) xs) (EnumFromTo 0 (Length xs - 1) :\\ ns) :++ Map ((:!!$$) ys) (EnumFromTo 0 (Length ys - 1) :\\ ms)) a tensordot x@(NDArray xs) y@(NDArray ys) (ns, ms) = result where range n = sEnumFromTo (sing :: Sing 0) (n %:- (sing :: Sing 1)) notinns = range (sLength xs) %:\\ ns notinms = range (sLength ys) %:\\ ms tx = transpose (notinns %:++ ns) x ty = transpose (ms %:++ notinms) y dimsIn xs = sMap (singFun1 (toProxy xs) (xs %:!!)) where toProxy :: Sing (shape :: [Nat]) -> Proxy (Apply (:!!$) shape) toProxy _ = Proxy (oldxs, oldys) = (dimsIn xs notinns, dimsIn ys notinms) where rtx = reshape (SCons (sProduct oldxs) $ SCons (sProduct $ dimsIn xs ns) SNil) tx rty = reshape (SCons (sProduct $ dimsIn ys ms) $ SCons (sProduct oldys) SNil) ty result = reshape (oldxs %:++ oldys) (rtx `dot` rty)
ã¨ããããã ãï¼ã³ã³ããã¹ãã«ããæ¡ä»¶ã®è¡¨ç¾ã¨ãã¦ã¯ï¼tensordotãåã2ã¤ã®ndarrayã®shapeã«å¯¾ãï¼dotãåãé¨åã®è»¸æå®ãpermutationã®é¨ååã«ãªã£ã¦ããï¼ãã¤ï¼æå®ããã軸ã«ã¤ãã¦åãå½¢ããã¦ããã¨ããæ¡ä»¶ç¸å½ãä»ãã¦ãããï¼
ãã®tensordotã®å®ç¾©ã¯åæ¤æ»ã«å¤±æãï¼5件ãããããç¡ãã¯ã»ã«ãã¼ã¿ã«1200è¡ãããã®é·å¤§ãªã¨ã©ã¼ã¡ãã»ã¼ã¸ãåãï¼ãã¡ããå®è£ è ãåãï¼ããã¦æ³£ãï¼ããã¯ï¼ãã³ã²ã³ã«ã¯èªæãªãã¨ã§ãã£ã¦ãï¼æ©æ¢°(åæ¤æ»å¨)ã«ã¯ããããªããã¨ãããããã ï¼ããã¯ï¼
- transposeæã®æ¡ä»¶ï¼è»¢ç½®æ¹æ³ãæ£ããpermutationã«ç¸å½ããå¤(åã¬ãã«ã®)ã«ãªã£ã¦ããããããããªãï¼(130è¡ã®ã¨ã©ã¼ x txã¨tyã«ã¤ãã¦2ç®æ)
- ãã³ã²ã³ã«ã¨ã£ã¦ï¼ããåã®ä¸ããããã¤ããåãåºã(notinnsãnotinms)ï¼åãåºããå¾ã®æåãæå¾ã«ãã£ã¤ãã¦(transposeã®å¼æ°)ãï¼é çªãå¤ããã ãã§ä¸èº«ã¯ä¸ç·(=permutation)ã§ãããã¨ã¯ãããï¼
- ãã©ï¼æ©æ¢°(åæ¤æ»å¨)ã«ã¨ã£ã¦ã¯èªæã§ã¯ãªãï¼
- reshapeæã®æ¡ä»¶ï¼reshapeåå¾ã®è¦ç´ æ°ã(åã¬ãã«ã§)åãã§ãããã©ãããããããªãï¼(280è¡ã®ã¨ã©ã¼ x rtxã¨rtyã«ã¤ãã¦2ç®æ + 400è¡ã®ã¨ã©ã¼ x resultã«ã¤ãã¦1ç®æ)
- ãã³ã²ã³ã«ã¨ã£ã¦ï¼ããæ£æ°ã®åã2ã°ã«ã¼ãã«åã(xsã«å¯¾ããoldxsã¨ãã以å¤ï¼ysã«å¯¾ããoldysã¨ãã以å¤)ï¼ããããã®ç©ãåã£ããã®ã®ç©ã¯ï¼å ã®åã®ç©ã¨åããã¨ã¯ãããï¼
- ãã©ï¼æ©æ¢°(åæ¤æ»å¨)ã«ã¨ã£ã¦ã¯èªæã§ã¯ãªãï¼
ãã¨ãããã¦ããï¼dotã®æ¡ä»¶ã«ã¤ãã¦ã®ã¨ã©ã¼ãåºã¦ããªããï¼ãã®æ¡ä»¶ã«ã¤ãã¦ã¯ããã£ã¦ããã®ãã¨ããã¨ï¼ããã¯tensordotèªä½ã®æ¡ä»¶(Mapã®ãã¤)ããæ©æ¢°(åæ¤æ»å¨)ã«ããããï¼ã¾ãï¼reshapableãtransposableçã§ä½¿ã£ãã¨ãåé¡ç¡ãã£ãã®ã¯ï¼å ·ä½çãªåã¬ãã«ã§ã®å¤(åã¬ãã«èªç¶æ°ãªãã©ã«)ãå ¥ã£ã¦ããããã§ããï¼å¯¾ãã¦ä»åã®tensordotã®å®ç¾©ä¸ã§ã¯(å)å¤æ°ã®ã¾ã¾ãªã®ã§ï¼æ©æ¢°(åæ¤æ»å¨)ãè¨ç®ãé²ãããããã®ç¶æ³ãç°ãªãï¼
ãã®ã¨ã©ã¼ã解決ããããã«ã¯ï¼æãã2ã¤æ¹æ³ãããï¼
- ç¡è¦ããï¼ã¨ãã£ã¦ãã¨ã©ã¼ã§ã¯ã©ããããããªãã®ã§前回の記事ã¨åããããªæ¹æ³ã使ãï¼transposeãreshapeã使ã£ã¦ãã¨ã©ã¼ã«ãªããªãã±ã¼ã¹ãä½ãåºãï¼ããã§ç¡è¦ããã®ã¯ä»¥ä¸2ç¹ã ï¼
- (ãã³ã²ã³ã¨ã£ã¦èªæã«unreachableãª)ã¨ã©ã¼ã±ã¼ã¹ãã³ã¼ãä¸çºçãããã¨
- ãããã使ã人ã«ã¯æ¡ä»¶ã示ããã¨ãè¦è«ããçã«ï¼èªåã使ãã¨ãã¯èªæã ããããã ãã¨ç¡è¦ããã«ãã³æªã
- 使ããæ å ±ããæ©æ¢°(åæ¤æ»å¨)ããããæ å ±ã«ãã³ã²ã³ãå¤æãã¦æãã¦ãããï¼
åè ã«ã¤ãã¦ï¼ãã³ã²ã³ã«ã¨ã£ã¦èªæã¨ã¯è¨ããã®ã®ï¼è¤éãªæ¡ä»¶ã«ãªãã¨æ¬å½ã«èªæãã©ããã¯ãã³ã²ã³ã«ãããããæªãããï¼ããããèªæã ã¨æã£ããã¨èªä½ãé¯èª¤ãããããªãï¼ããããåã¬ãã«ã§ã©ãã«ããããã¨ãã話èªä½ï¼ãããã£ããã³ã²ã³ã«ãããã¹ãã©ãã«ããããã¨ããã¢ããã¼ã·ã§ã³ã ã£ãçã§ããï¼è§£æ±ºã®æ¹åæ§ã¨ãã¦ã¯ã©ããªã®ã½ã¬ã¨ããæãããï¼
å¾è ãæ£æ»æ³ã¨ãªããï¼å®ã¯ï¼ããããã®çéã§ä½ã¨å¼ã°ãã¦ãããç§éã¯æ¢ã«ç¥ã£ã¦ããï¼ããã¯å®ç証æã¨å¼ã°ããã¤ãã§ããï¼ãããªãã¨ã¯ã³ãã£ã³è¨¼æå¨ããextractããã»ãã使ãæãã¾ã§ããï¼Haskellã§ãå®éGHC.TypeLits.Natã¯ãã¢ãæ°ã§ã¯ãªã*2ãããªã®ã§ï¼ãã®ã¾ã¾ã§ã¯Inductionãå¹ãã証æç¸å½ã®ãµã®ã§ã¦ãããã«ãããã¨ãã®ä¸ç¡ãã£ããããï¼
ã¾ã¨ããã¨ï¼å種å¥ç´ãåã§äºã ï½ã«æå¾ ãããããã¬ãã¬ãã«åã¬ãã«ã§è¨è¨ããããã®ã¯ï¼è¨èªã«ã使ãå´ã«ãåã¬ãã«ã§ã¬ããªåãçµã¿ãæ±ãããããã¨ãããï¼åã¬ãã«ã¸æ¡ä»¶ãæã¡ä¸ãããã¨ã¯ã人ã¯ãã¹ããã«ä½æ¥ãã§ããããã¨ããåé¡ãã人ã¯å®ç証æãã§ããããã¨ããåé¡ã¸ã¨å¤æãããã¨ãªã®ã ï¼ã¨ãªãã¨ï¼æè¿nullå®å ¨ï¼ã¨ãã®è©±ããè¤éãªå¥ç´ãåã§ã¤ãã¿ã¼ï¼ã¨è¨ã£ã¦ãæ¹ã ã¯ãã¶ãçãã®ã¸ãã«ã¤ãã¦ããè¦æå®äºï¼å½æ¹ã«è¿æã®æºåæãï¼ããªã®ã§ï¼å®ç証æã«ã¤ãã¦ãä½ã§ã*3èãã¦å¤§ä¸å¤«ã¨ãããã¨ã«ãªãï¼ãã£ãã
*1:ChainerããTensorFlowããã§æéããããå¦ç¿å¾ã»ã¼ããããå°ããããã¼ã¿(ã®shape)ééãããã¨ã
*2:ãããããªãã§ãããªã£ã¦ããã ã£ãï¼åã¬ãã«èªç¶æ°ãªãã©ã«ã¯ãã¢ãæ°ã¸ã®ã¨ã¤ãªã¢ã¹ã§ããã£ãããã«ãæããã ãã©
*3:ãï¼ä»