質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.83%

  • C++

    3142questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

ファジィ識別器について

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 224

pontyo

score 2

#include <iostream>
#include<fstream>
#include<sstream>
#include<cmath>
#include<stdio.h>
#include<stdlib.h>
//データ数
#define N 61
//次元数
#define N_d 2
//クラス数
#define N_c 3
//個体群サイズ(ルール数)
#define N_rp 16
using namespace std;
class Fuzzy {
public:
   //コンストラクタ
   Fuzzy() {
       //ファジィルール初期化
       int i = 0;
       int j = 0;
       rule[0][0] = 1;
       rule[1][0] = 1;
       rule[2][0] = 1;
       rule[3][0] = 1;
       rule[4][0] = 2;
       rule[5][0] = 2;
       rule[6][0] = 2;
       rule[7][0] = 2;
       rule[8][0] = 3;
       rule[9][0] = 3;
       rule[10][0] = 3;
       rule[11][0] = 3;
       rule[12][0] = 0;
       rule[13][0] = 0;
       rule[14][0] = 0;
       rule[15][0] = 0;
       rule[0][1] = 1;
       rule[1][1] = 2;
       rule[2][1] = 3;
       rule[3][1] = 0;
       rule[4][1] = 1;
       rule[5][1] = 2;
       rule[6][1] = 3;
       rule[7][1] = 0;
       rule[8][1] = 1;
       rule[9][1] = 2;
       rule[10][1] = 3;
       rule[11][1] = 0;
       rule[12][1] = 1;
       rule[13][1] = 2;
       rule[14][1] = 3;
       rule[15][1] = 0;
       //ルール選択配列初期化
       for (int i = 0; i<N_rp; i++) {
           rule_select[i] = 1;
           rule_select_2[i] = 1;
       }
       fitness = 0;
   }
       //学習用データの読み込み
   void read_data() {

       double data1x[N][N_d];
       double x1[N];   //臨時配列(パターン1)
       double x2[N];   //臨時配列(パターン1)
       int c11[N];   //臨時配列(パターン1)
       int i = 0;
       FILE *fp1;
       errno_t error1;
       if ((error1 = fopen_s(&fp1, "kadai3_pattern1.txt", "r")) != 0) {
           printf("cannot open the file\n");
       }
       else {
           while (fscanf_s(fp1, "%lf,%lf,%d", &x1[i], &x2[i], &c11[i]) != EOF) {
               data[i][0] = x1[i];
               data[i][1] = x2[i];
               data[i][2] = (double)c11[i];
               i++;
           }
       }
       fclose(fp1);
       //データの格納終了
   }
   //適合度計算
   void calc_fit() {
       double a, tmp, fit;
       for (int h = 0; h < N_rp; h++) {
           for (int i = 1; i <= N; i++) {
               fit = 1;
               //各ルールでの各データパターンでの適合度計算
               for (int j = 0; j < N_d; j++) {
                   //don't care ならメンバシップ値は1
                   if ((int)rule[h][j] == 0)continue;
                   a = (double)(rule[h][j] - 1) / 2;
                   tmp = 1 - 2 * abs(a - data[i][j]);
                   if (tmp > 0) {
                       fit *= tmp;
                   }
                   else {
                       fit = 0;
                       break;
                   }
               }
               rule_fit[h][i - 1] = fit;
           }
       }
   }
   //信頼度計算
   void calc_trust() {
       //適合度の和を入れる tmp2はクラスhを指すデータの適合度の和
       double tmp, tmp2;
       for (int k = 0; k < N_rp; k++) {
           //クラスは3種
           for (int i = 0; i < 3; i++) {
               tmp = 0;
               tmp2 = 0;
               for (int j = 1; j <= N; j++) {
                   if ((int)data[j][2] == i) {
                       tmp2 += rule_fit[k][j - 1];
                   }
                   tmp += rule_fit[k][j - 1];
               }
               rule_class[k][i] = tmp2 / tmp;
           }
       }
   }
   //各ルール結論クラス決定
   void calc_class() {
       double tmp;
       int tmp_class;
       for (int i = 0; i <N_rp; i++) {
           tmp = rule_class[i][0];
           tmp_class = 0;
           //最も信頼度の高いクラスに決定
           for (int j = 1; j <3; j++) {
               if (tmp < rule_class[i][j]) {
                   tmp = rule_class[i][j];
                   tmp_class = j;
               }
           }
           //結論部クラス決定
           rule[i][2] = tmp_class;
           //ルール重み計算
           for (int j = 0; j <3; j++) {
               if (j != tmp_class) {
                   tmp -= rule_class[i][j];
               }
               //ルール重みが0以下ならそのルールは不要
               if (tmp <= 0) {
                   rule[i][4] = 0;
                   break;
               }
               rule[i][3] = tmp;
           }
       }
   }
   //総ルール長とルール数の計算
   void count_rule() {
       rule_len = 0;
       rule_num = 0;
       for (int i = 0; i<N_rp; i++) {
           if ((int)rule[i][4] == 1 && rule_select[i] == 1) {
               if ((int)rule[i][0] != 0)rule_len++;
               rule_num++;
               if ((int)rule[i][1] != 0)rule_len++;
           }
       }
   }
   //識別率計算
   void calc_ans() {
       double tmp;
       //異なる結論クラスを持つが適合度とルール重みの和が等しくなった時にチェック
       bool check = false;
       //それぞれ正解した数、合計数
       int collect_num = 0;
       int sum = 0;
       double win_tmp = 0;
       int win_num = 0;
       for (int j = 1; j <= 60; j++) {
           win_tmp = 0;
           win_num = 0;
           check = false;
           for (int i = 0; i < N_rp; i++) {
               //勝者ルールの決定
               //不使用ルール
               if ((int)rule[i][4] == 0 || rule_select[i] == 0)continue;
               tmp = rule[i][3] * rule_fit[i][j - 1];
               if (win_tmp < tmp) {
                   win_tmp = tmp;
                   win_num = i;
                   check = false;
               }
               else if (tmp == 0)continue;
               else if ((win_tmp == tmp) && (rule[win_num][2] != rule[i][2])) check = true;
           }
           //勝者ルールでの識別
           if (check == true)continue;
           else if (data[j][2] == rule[win_num][2])collect_num++;
           sum++;
       }
       ans_rate = collect_num / (double)sum;
   }
   //識別率、総ルール数、ルール長の表示
   void show1() {
       cout << "calc:" << ans_rate << endl;
       cout << "rule_num:" << rule_num << endl;
       cout << "rule_len:" << rule_len << endl;
   }
   //識別率、総ルール数、ルール長の表示
   void show2() {
       cout << "calc:" << ans_rate_2 << endl;
       cout << "rule_num:" << rule_num_2 << endl;
       cout << "rule_len:" << rule_len_2 << endl;
   }
   //ファジィルール集合選択
   void create_rule(int num) {
       if (num == 0) {
           for (int i = 0; i < 2; i++) {
               rule_select[num] = i;
               //識別率の計算
               calc_ans();
               //ルール数と相ルール長の計算
               count_rule();
               //加重和適応度の計算
               if ((1000 * ans_rate - rule_num - rule_len) > fitness) {
                   fitness = 1000 * ans_rate - rule_num - rule_len;
                   ans_rate_2 = ans_rate;
                   rule_len_2 = rule_len;
                   rule_num_2 = rule_num;
                   for (int j = 0; j<N_rp; j++) {
                       rule_select_2[j] = rule_select[j];
                   }
               }
           }
       }
       else {
           for (int i = 0; i<2; i++) {
               rule_select[num] = i;
               create_rule(num - 1);
           }
       }
   }
protected:
   ///////////////////データ読み込みに関するメンバ
   //学習データ格納 要素,クラスの順 0行目は入力データの情報 1行目からデータ
   double data[N][N_d + 1];
   //ルール配列 条件ファジイ集合,結論クラス,ルール重み、利用bitの順 利用bitが1ならそのルールは使用しない
   double rule[N_rp][5];
   //各ルールの適合度計算
   double rule_fit[N_rp][N];
   //各ルールの信頼度計算
   double rule_class[N_rp][3];
   //ルール数
   int rule_num;
   //総ルール長
   int rule_len;
   //識別率
   double ans_rate;
   //ルール集合選択配列
   int rule_select[N_rp];
   //加重和適応度
   double fitness;
   //ルール集合選択後の結果
   //ルール数
   int rule_num_2;
   //総ルール長
   int rule_len_2;
   //識別率
   double ans_rate_2;
   //ルール集合選択配列
   int rule_select_2[N_rp];
};
int main() {
   ////////////////準備///////////////////////
   //オブジェクト生成
   Fuzzy fuzzy;
   //学習データ読み込み
   fuzzy.read_data();
   /////////////////////学習開始/////////////////////////
   ////適合度計算
   fuzzy.calc_fit();
   ////信頼度計算
   fuzzy.calc_trust();
   ////結論部クラス決定、ルール重み計算
   fuzzy.calc_class();
   fuzzy.count_rule();
   ////////////未知パターン識別////////////////
   ////識別率計算
   fuzzy.calc_ans();
   fuzzy.show1();
   ////ファジィルール選択
   fuzzy.create_rule(15);
   fuzzy.show2();
   return 0;
}


ファジィ識別器をC++で作成しています。show1,show2関数で識別率、ルール数、総ルール長を表示するようにしています。実行結果は、show1では、順に91.667,0,0となり、show2では93.0,0,0となりました。識別率に関しては正解データと一致しました。ただ、ルール数と総ルール長はshow1に関しては13,22で、show2に関しては5,8が正解となります。どこで間違っているのかがよく分からないのでよろしければ教えてください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正の依頼

  • 退会済みユーザー

    退会済みユーザー

    2018/01/18 22:08

    本文を質問の内容がわからないレベルまで変えないでください。

    キャンセル

  • 退会済みユーザー

    2018/01/18 23:19

    複数のユーザーから「意図的に内容が抹消された質問」という意見がありました
    解決後に編集機能を用いて質問内容を改変し関係のない内容にしたり、内容を削除する行為は禁止しています。
    投稿していただいた質問は、後に他の誰かが困ったときに助けになる情報資産になると考えるからです。
    「質問を編集する」ボタンから編集を行い、他のユーザにも質問内容が見えるように修正してください。

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.83%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C++

    3142questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。