Esempio n. 1
0
        public void Update(Real[] scoreDrop, Real[] scoreGrow, NdArray <Real> mask, NdArray <Real> weight)
        {
            int nOnes  = (int)mask.Data.Sum();
            int nPrune = (int)Math.Floor(nOnes * _dropFraction);//元実装はキャストで切り捨てしている
            int nKeep  = nOnes - nPrune;

            int[] keepMask = new int[mask.Data.Length];
            Real  chackval = scoreDrop.OrderBy(a => - a).ElementAt(nKeep);

            //mask1にScoreDropの大きい順の先頭nKeep個に1を入れる
            for (int i = 0, keepCount = 0; i < keepMask.Length && keepCount < nKeep; i++)
            {
                if (scoreDrop[i] >= chackval)
                {
                    keepMask[i] = 1;
                    keepCount++;
                }
            }

            Real[] scoreGrowLifted = new Real[scoreGrow.Length];

            //有効になっている接続のスコアが最も低くなるようにする //元実装だとscoreGrow.Min() - 1.0f
            for (int i = 0; i < keepMask.Length; i++)
            {
                scoreGrowLifted[i] = keepMask[i] == 1 ? Real.MinValue : scoreGrow[i];
            }

            int[] growMask = new int[scoreGrowLifted.Length];

            chackval = scoreGrowLifted.OrderBy(a => - a).ElementAt(nPrune);

            //mask2にscoreGrowLiftedの大きい順の先頭nPrune個に1を入れる
            for (int i = 0, prunedCount = 0; i < growMask.Length && prunedCount < nPrune; i++)
            {
                if (scoreGrowLifted[i] > chackval)
                {
                    growMask[i] = 1;
                    prunedCount++;
                }
            }

#if DEBUG
            //mask1 * mask2で全て0になるか確認
            int sum = 0;
            for (int i = 0; i < keepMask.Length; i++)
            {
                sum += keepMask[i] * growMask[i];
            }

            if (sum != 0)
            {
                throw new Exception();
            }
#endif
            //Real[] glowTensor = getGlowTensor() //元実装がデフォルトだと0固定なので省略

            bool[] newConnections = new bool[weight.Length];

            for (int i = 0; i < weight.Length; i++)
            {
                newConnections[i] = growMask[i] == 1 && mask.Data[i] == 0;

                //マスクの更新があるか判定
                if (newConnections[i])
                {
                    weight.Data[i] = 0; // この0は本来はgetGlowTensor()で取得してきたglowTensor;
                }
            }

            ResetMomentum(newConnections, scoreGrow, weight.Name);

            for (int i = 0; i < mask.Length; i++)
            {
                //mask1 * mask2で全て0になる保証があるので
                mask.Data[i] = keepMask[i] + growMask[i];
            }
        }