Exemplo n.º 1
0
 /// <summary>
 /// Создается единственное состояние
 /// </summary>
 /// <param name="var">Лингвистическая переменная к которой привязано условие</param>
 /// <param name="term">Терм в выражении "Переменная есть терм"</param>
 /// <param name="not">Содержит ли состояние отрицание</param>
 /// <returns>Созданное состояние</returns>
 public FuzzyCondition CreateCondition(FuzzyVariable var, FuzzyTerm term, bool not)
 {
     return(new FuzzyCondition(var, term, not));
 }
Exemplo n.º 2
0
 /// <summary>
 /// Создается единственное состояние
 /// </summary>
 /// <param name="var">Лингвистическая переменная к которой привязано условие</param>
 /// <param name="term">Терм в выражении "Переменная есть терм"</param>
 /// <param name="not">Содержит ли состояние отрицание</param>
 /// <param name="type">Модификатор</param>
 /// <returns>Созданное состояние</returns>
 public FuzzyCondition CreateCondition(FuzzyVariable var, FuzzyTerm term, bool not, HedgeType type)
 {
     return(new FuzzyCondition(var, term, not, type));
 }
Exemplo n.º 3
0
        /// <summary>
        /// Обучение Fis
        /// </summary>
        /// <param name="anfisTrain">Функция обучения</param>
        public void Train(anfisTrain anfisTrain = null)
        {
            //
            // Генерация Fis
            //
            Genfis();
            //
            // Обучение Fis
            //
            int    epoch = 1;
            double epochError;

            if (Rules.Count == 0)
            {
                throw new Exception("Должно быть хотя бы одно правило.");
            }

            int k = xout.Length;                            // Количество параметров обучающей выборки
            int l = (xin.Length + 1) * Rules.Count;         // (m+1)n - m - количество входных переменных n - количество правил

            Matrix C = new Matrix(l, 1);                    // Столбец весовых коэффициентов
            Matrix Y = new Matrix(k, 1);                    // Вектор столбец выходных данных

            for (int i = 0; i < k; i++)
            {
                Y[i, 0] = xout[i];
            }

            errorTrain = new double[Epochs];
            while (epoch <= Epochs)
            {
                epochError = 0.0;                           // Ошибка на i эпохе
                //
                // Формирование матрицы коэффициентов
                //
                Matrix W  = new Matrix(k, l);
                Matrix ew = new Matrix(k, Rules.Count);
                for (int i = 0; i < k; i++)
                {
                    Dictionary <FuzzyVariable, double> inputValues = new Dictionary <FuzzyVariable, double>();
                    // По количеству переменных
                    for (int j = 0; j < xin.Length; j++)
                    {
                        inputValues.Add(InputByName(NameInput + (j + 1).ToString()), xin[j][i]);
                    }
                    // Посылки правил
                    Dictionary <FuzzyVariable, Dictionary <FuzzyTerm, double> > fuzzyInput = Fuzzify(inputValues);
                    // Агрегирование подусловий
                    Dictionary <SugenoFuzzyRule, double> rulesWeight = EvaluateConditions(fuzzyInput);
                    // Заключение правил
                    double        Stau = 0.0;
                    List <double> tau  = new List <double>();
                    foreach (double _tau in rulesWeight.Values)
                    {
                        Stau += _tau;
                        tau.Add(_tau);
                    }
                    double[] b = new double[tau.Count];
                    for (int j = 0; j < b.Length; j++)
                    {
                        b[j]     = tau[j] / Stau;
                        ew[i, j] = tau[j];
                    }
                    // Формирование входных переменных
                    double[] x = new double[xin.Length + 1];        // +1, т.к. x0 = 1
                    x[0] = 1;                                       // x0 = 1
                    for (int j = 1; j < x.Length; j++)
                    {
                        x[j] = xin[j - 1][i];                       // заполняем x1, x2,...,x3
                    }
                    int columnW = 0;
                    for (int g = 0; g < b.Length; g++)              // перебираем по заключениям
                    {
                        for (int d = 0; d < x.Length; d++)          // перебираем по входным данным
                        {
                            W[i, columnW] = b[g] * x[d];            // переменожаем коэффициенты на переменные
                            columnW++;                              // увеличиваем строку на 1
                        }
                    }
                }

                Matrix Winverse = W.PInverse();     // W+ псевдоинверстная матрица

                //
                // Если псевдоинверстная матрица не найдена
                //
                bool breakTrain = false;
                for (int i = 0; i < Winverse.N; i++)
                {
                    for (int j = 0; j < Winverse.M; j++)
                    {
                        if (double.IsNaN(Winverse[i, j]))
                        {
                            breakTrain = true;
                            break;
                        }
                    }
                    if (breakTrain)
                    {
                        break;
                    }
                }
                if (breakTrain)
                {
                    break;              // Прерываем обучение
                }
                C = Winverse * Y;       // Находим коэффициенты
                //
                // Нахождение вектора фактического выхода сети
                //
                Matrix Ystrich = W * C;
                //
                // Правим коэффициенты
                //
                for (int i = 0; i < Input.Count; i++)
                {
                    FuzzyVariable fv = Input[i];                // Забираем переменную
                    for (int j = 0; j < fv.Terms.Count; j++)
                    {
                        FuzzyTerm term = fv.Terms[j];               // Выбираем j терм i входной переменной
                        //
                        // Меняем в случае если функция принадлежности колоколообразная
                        //
                        IMembershipFunction mf = term.MembershipFunction;
                        if (mf is NormalMembershipFunction)
                        {
                            NormalMembershipFunction mfterm = (NormalMembershipFunction)mf;  // Приводим тип
                            //
                            // Перебираем все переменные k - количество выходных параметров
                            //

                            for (int g = 0; g < k; g++)
                            {
                                double b     = mfterm.B;
                                double sigma = mfterm.Sigma;
                                double xa    = xin[i][g] - b;             // xin - b

                                double yyStrih = Ystrich[g, 0] - xout[g]; // y' - y
                                double p       = ew[g, j];
                                double sp      = 0.0;
                                for (int q = 0; q < Rules.Count; q++)
                                {
                                    sp += ew[g, q];
                                }
                                double pb = p / (sp / Math.Pow(sigma, 2));   // (t/summt) / sigma^2
                                //
                                // Инициализируем матрицы для нахождения c
                                //
                                Matrix x = new Matrix(1, xin.Length + 1);
                                Matrix c = new Matrix(xin.Length + 1, 1);
                                x[0, 0] = 1;                                 //x0 = 1
                                for (int q = 1; q < x.M; q++)
                                {
                                    x[0, q] = xin[q - 1][g];
                                }
                                // Заполняем коэффициенты
                                int start = j * x.M;
                                for (int q = start; q < start + x.M; q++)
                                {
                                    c[q - start, 0] = C[q, 0];
                                }

                                // Перемножаем матрици
                                double cy = ((x * c)[0] - Ystrich[g, 0]);
                                //
                                // Корректируем B
                                //

                                b -= 2 * Nu * xa * yyStrih * cy * pb;

                                //
                                // Корректируем Sigma
                                //

                                sigma -= 2 * Nu * Math.Pow(xa, 2) * yyStrih * cy * pb;
                                //
                                // Условия переобучения и недопустимости применения условий
                                //

                                if (double.IsNaN(mfterm.Sigma) || double.IsNaN(mfterm.B))
                                {
                                    continue;   // Идем на следующую итерацию
                                }
                                else
                                {
                                    mfterm.B     = b;
                                    mfterm.Sigma = sigma;
                                }
                            }
                            //
                            // Загоняем терм обратно
                            //



                            fv.Terms[j].MembershipFunction = mfterm;
                        }
                        //
                        // TODO: Настройка остальных функций принадлежности не реализовано
                        //
                    }

                    Input[i] = fv;                      // Загоняем переменную обратно
                }
                //
                // Находим ошибку выхода
                //
                epochError = 0.0;
                for (int i = 0; i < Ystrich.N; i++)
                {
                    epochError += 0.5 * Math.Pow(Ystrich[i, 0] - xout[i], 2);
                }
                errorTrain[epoch - 1] = epochError;
                anfisTrain?.Invoke(epoch, Epochs, nu, epochError);
                Nu *= NuStep;
                epoch++;
            }   // Конец эпох обучения

            //
            // Применяем параметры коэффициентов y = c0 + c1 * x1 + c2 * x2 + ... + ci * xi
            //
            SetCoefficient(C);
            //
            // Перезаписываем правила в силу архитектуры сети
            //
            Rules.Clear();
            for (int i = 0; i < rulesText.Length; i++)
            {
                Rules.Add(ParseRule(rulesText[i]));
            }

            Console.WriteLine(Rules[0].ToString());
        }