• 締切済み

人工的なデータを作成するアルゴリズム

人工的なデータを作成するアルゴリズムを探しています。 条件は, 1. データの個数はN=500個を3セット 2. それぞれのセットは1から500までの整数を並べ替えたもの 3. セット間の相関係数は,セット1とセット2が0.7,セット1とセット3が0.6,セット2とセット3が0.5とします。 このうち条件1と条件2は絶対です。条件3はできるだけ近ければよいとします。 どのようにして作成すれば良いでしょうか?

  • f272
  • お礼率100% (8/8)

みんなの回答

回答No.1

探索すべき対象が非常に多く、期待している相関係数は比較的大きいです。そこでリスト [1, 2, ..., 500] をふたつに分けひっくり返した形のものだけを探してみました。 セット1 = x = [1, 2, ..., 500], セット2 = y = [22, 23, ..., 500, 1, 2, ..., 21], セット3 = z = [470, 471, ..., 500, 1, 2, ..., 469] を考えると相関係数はおよそ r(x, y) ~ 0.76, r(x, z) ~ 0.65, r(y, z) ~ 0.44 となります。これくらいではいかが? 以下、計算に使ったpythonのコード(どうもインデントが正しく表示できないようですが、理解する上で特に問題はないでしょう)。計算はラップトップで一分ほどでした。 from scipy.stats import pearsonr N = 500 a = range(1, N+1) def r(x, y): return pearsonr(x, y)[0] def rev(n): return a[n:] + a[:n] ## find date set score = float("inf") x = rev(0) for j in range(N): y = rev(j) score1 = (r(x, y) - 0.7)**2 for k in range(N): z = rev(k) score2 = (r(x, z) - 0.6)**2 + (r(y, z) - 0.5)**2 if score1 + score2 < score: score = score1 + score2 j0 = j; k0 = k ## result x = rev(0); y = rev(j0); z = rev(k0) print j0, k0 print r(x, y), r(x, z), r(y, z)

f272
質問者

お礼

ありがとうございます。 結局のところ,以下のようにしました。9セット分のデータを作成しても0.3秒ですので,十分に実用に耐えます。 簡単にやり方を説明すると, 1.一様乱数を必要なセット数だけ発生させる。 2.各データセットを与えられた相関があるように変換する。 3.変換後のデータセットをそれぞれ順位づけして1から500までの整数に変換する。 相関係数は 1.0 0.6,1.0 0.2,0.1,1.0 0.1,0.2,0.7,1.0 0.1,0.2,0.6,0.6,1.0 0.1,0.2,0.1,0.1,0.1,1.0 0.1,0.2,0.1,0.2,0.2,0.6,1.0 0.1,0.1,0.1,0.1,0.1,0.1,0.1,1.0 0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.6,1.0 を目標にしていますが,実際に得られた相関係数は以下のとおりです。 1.000 0.585,1.000 0.231,0.097,1.000 0.191,0.219,0.726,1.000 0.159,0.217,0.570,0.591,1.000 0.107,0.170,0.075,0.031,0.082,1.000 0.059,0.178,0.040,0.112,0.152,0.565,1.000 0.174,0.178,0.168,0.166,0.176,0.127,0.120,1.000 0.153,0.203,0.152,0.093,0.133,0.124,0.100,0.591,1.000 #include<iostream> #include<iomanip> #include<algorithm> #include<random> using std::begin; using std::end; using std::cout; using std::endl; inline double sqr(double v) {return v*v;} double pearsonr(double *x,double *y,int n) { double sx=0.0,sy=0.0,sxy=0.0,sxx=0.0,syy=0.0; int i; for (i=0;i<n;++i) { sx+=x[i]; sy+=y[i]; } double mx=sx/n,my=sy/n; for (i=0;i<n;++i) { sxy += (x[i]-mx)*(y[i]-my); sxx += sqr(x[i]-mx); syy += sqr(y[i]-my); } return sxy/sqrt(sxx*syy); } int main() { int i,j,k; const int NSET=9; const int N=500; double x[NSET][N],y[NSET][N]; double r[NSET][NSET],r1[NSET][NSET],s; double r0[NSET][NSET]={{1.0}, {0.6,1.0}, {0.2,0.1,1.0}, {0.1,0.2,0.7,1.0}, {0.1,0.2,0.6,0.6,1.0}, {0.1,0.2,0.1,0.1,0.1,1.0}, {0.1,0.2,0.1,0.2,0.2,0.6,1.0}, {0.1,0.1,0.1,0.1,0.1,0.1,0.1,1.0}, {0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.6,1.0}, }; for (i=0;i<NSET;++i) { s=0.0; for (j=0;j<=i;++j) { if (j<i) { r1[i][j]=r0[i][j]; for (k=0;k<j;++k) r1[i][j]-=r1[j][k]*r1[i][k]; if (0<j) r1[i][j]/=r1[j][j]; s+=sqr(r1[i][j]); } else r1[i][j]=sqrt(1-s); } } // 一様分布で作成 std::random_device rnd; std::mt19937 mt(rnd()); std::uniform_real_distribution<> rand01(0.0, 1.0); for (i=0;i<NSET;++i) { for (j=0;j<N;++j) { x[i][j]=rand01(mt); } } // 相関付ける for (i=0;i<NSET;++i) { for (j=0;j<N;++j) { y[i][j]=0.0; for (k=0;k<=i;++k) { y[i][j] += x[k][j]*r1[i][k]; } } } struct R { double val; int rank; int id; } data[N]; for (i=0;i<NSET;++i) { for (j=0;j<N;++j) { data[j].id = j; data[j].val = y[i][j]; } // valでソートする auto val_more = [](const R& x, const R& y) { return x.val < y.val; }; std::sort(begin(data), end(data), val_more); // 順位づけ for (j=0;j<N;++j) { data[j].rank = static_cast<int>(std::distance(begin(data), std::lower_bound(begin(data), end(data), data[j], val_more)))+1; } // idでソートする auto id_more = [](const R& x, const R& y) { return x.id < y.id; }; std::sort(begin(data), end(data), id_more); // for (j=0;j<N;++j) x[i][j]= data[j].rank; } // 順位付けに従った値になったので,相関係数を検証する for (i=0;i<NSET;++i) { for (j=0;j<NSET;++j) { r[i][j]=pearsonr(x[i],x[j],N); } } cout << "r="; for (i=0;i<NSET;++i) { for (j=0;j<=i;++j) cout << "\t" << std::fixed << std::setprecision(3) << r[i][j]; cout << endl; } cout << endl; cout << resetiosflags(std::ios_base::floatfield); cout << "x="; for (i=0;i<N;++i) { for (j=0;j<NSET;++j) cout << "\t" << x[j][i]; cout << endl; } cout << endl; cout << endl; } 復活

f272
質問者

補足

以下のように書いてみると約0.3秒で答えがでます。しかし,実際にやりたかったことは3セットではなく9セットなのです。同じように書いてみても実際的な計算時間では収まりません。4セットですら約38秒かかります。 その上,9セットは大まかには2-3-2-2のサブセットに分かれていて,与えられる相関係数はサブセット内は大きく0.63くらいですが,サブセット間は小さくて約0.07です。 なにか画期的な方法はないものでしょうか? #include<iostream> #include<cmath> inline double sqr(double v) {return v*v;} double pearsonr(double *x,double *y,int n) { double sx=0.0,sy=0.0,sxy=0.0,sxx=0.0,syy=0.0; int i; for (i=0;i<n;++i) { sx+=x[i]; sy+=y[i]; } double mx=sx/n,my=sy/n; for (i=0;i<n;++i) { sxy += (x[i]-mx)*(y[i]-my); sxx += sqr(x[i]-mx); syy += sqr(y[i]-my); } return sxy/sqrt(sxx*syy); } int main() { double x[1000]; double r[3][3],rr[3][3],s[3]; double r0[3][3]={{1.0}, {0.7,1.0}, {0.6,0.5,1.0}, }; int n=500; int i,j,k[3],kk[3]; for (i=0;i<n;++i) { x[i]=x[i+n]=i+1; } double ss=999; kk[0]=k[0]=0; for (k[1]=1;k[1]<n;++k[1]) { r[1][0] = pearsonr(x+k[1],x+k[0],n); s[1]=sqr(r[1][0]-r0[1][0]); if (ss<s[1]) continue; for (k[2]=1;k[2]<n;++k[2]) { for (i=0;i<2;++i) r[2][i] = pearsonr(x+k[2],x+k[i],n); s[2]=s[1]; for (i=0;i<2;++i) s[2]+=sqr(r[2][i]-r0[2][i]); if (ss>s[2]) { ss=s[2]; for (i=1;i<3;++i) { kk[i]=k[i]; for (j=0;j<i;++j) rr[i][j]=r[i][j]; } } } } std::cout << "kk="; for (i=1;i<3;++i) std::cout << " " << kk[i]; std::cout << std::endl; std::cout << "r="; for (i=1;i<3;++i) { for (j=0;j<i;++j) std::cout << " " << rr[i][j]; std::cout << std::endl; } std::cout << std::endl; }

関連するQ&A

  • アルゴリズムとデータの個数

    各種配列アルゴリズムのデータ個数と処理時間による比較を行って、このとき,処理時間の平均値を用いたのですが、整列一歩手前等,特別な条件下では処理時間が入れ替わることがありそれはどのようなアルゴリズムの場合かおしえてくれませんか?

  • C++でのアルゴリズム

    次の条件を満たすアルゴリズムをC++のコードで教えてください! 大きさ2×1の長方形n個を 縦2 横n の長方形になるように並べるときの並べ方の総数を求めるアルゴリズム 入力nは、1以上の整数が入力される前提でよい。 例として、 n=1 1通り n=2 2通り n=3 3通り n=5 8通り n=7 21通り となります お願いします。

  • 相関係数を指定して二変量データを作成する

    相関係数、平均、標準偏差を指定して二変量データを作成しようとしていますが、なかなかうまくいきません。 http://oshiete1.goo.ne.jp/qa2413827.html こちらの回答を参考にしてエクセルで試してみたのですが、出力されたデータの相関係数、平均、標準偏差を調べて見るとどの値も微妙にずれてしまいます。

  • アルゴリズム

    アルゴリズムの勉強をしていて、時間計算量に関する問題があり、解いたのですが、解答が載ってなく困ってます。正誤の判断と、もし間違っているなら、何が間違っているのかを教えて頂けると助かります。 ある問題において、大きさ(データ量)nに対して、アルゴリズムA、B、Cの時間計算量が、それぞれn、n^2(nの2乗)、2^n(2のn乗)であるとする。 (1)アルゴリズムAを用いて10秒間にn=100の問題が解けた。20秒かけるとき扱える問題の大きさnの値を求めよ。 解) n=100*2 =200 (2)ある計算機を用いてアルゴリズムBで10秒間にn=100の問題が解けた。100倍早い計算機を用いたとき、10秒間に扱える問題の大きさを求めよ。 解) 求める問題の大きさをxとおくと n=(100^2)*100 =10000*100 =1000000 (3)アルゴリズムCを用いて1時間にn=20の問題が解けた。n=40の問題を解くのに何時間かかるか。 解) 2^40=(2^20)*(2^20) =1*(2^20) =2^20[時間]

  • 標準偏差,相関係数が綺麗になるデータの求め方

    標準偏差,相関係数がある程度綺麗になる(小数第2位程度まで)ようなデータを人工的に作りたいのですが,何か良い方法はありますでしょうか。 理想としては,プログラミングを用いてデータと標準偏差,相関係数がそれぞれ出力されるのが良いですが,より良い方法があるならば教えて頂きたいです。 プログラミングならばその内容まで教えて頂けると幸いです。 なお,データの数は5~20個程度で,数値は1~3桁です。 よろしくお願い致します。

  • アルゴリズムについて

    整数nが与えられたとき、n×nのサイズで螺旋状に 0から(n×n-1)までの数字が並ぶ行列を作成し、 画面に表示するようなプログラムを教えてください。 出力するとこんな感じに表示されると思います。 n=4のとき 0 1 2 3 11 12 13 4 10 14 15 5 9 8 7 6

  • データの系列の平均の求め方のアルゴリズム

    100個の数値が並んでいてその平均を求めるという場合、全部足して100で割る、ということしか考えられなかったのですが、そうではないアルゴリズムがあるようです。プログラム的な説明だと以下のようです。 ave=0.0 平均が分かっていると仮定する。 do i=1,100 xx=x(i)-ave あるデータx(i)と、分かっている思っている平均aveとの差をとる。 ave=ave+xx/i その差をそこまでのデータ個数iで割る。新しいデータによる平均の変化量とみてそれを前の平均に加える。 enddo それを十分大きな回数繰り返す。そうすると平均に近づく。 このような考え方はある学問分野では常識なのかもしれませんが、近似ということになると思います。データの数が十分大きくて最初の平均が実際と異なるエラーが相対的に減ってくるとかです。このアルゴリズムにはどのような制約が付くものでしょうか。例えば乱数を発生させてその平均を求めるときに全部発生させてから和を取って個数で割るのではなく、1つ1つ乱数を発生させて発生し終わった時点で平均が計算できてしまっている、ということになります。分散も同じようなアルゴリズムになると思います。実験や理論的な検討を加えることはできると思いますが、あまりにも簡単なので常識であり、かつ性質も調べられているのではないかと思ってお尋ねしました。いかがでしょうか。

  • 人工知能の作り方

    最近すごく人工知能について興味を持っているんですけど。 実際に人工知能はどのようなアルゴリズムで動いているのか どのようなソースで動いているのかまったくわかりません。 高卒程度の学力しかない自分でも果たして人工知能は作れるのでしょうか? どのようなことを勉強すれば人工知能を作成できるのでしょうか? できればわかりやすい参考書などを教えていただけるとありがたいです。 決してむずかしいものを作ろうとはまだしていませんので、 どうか、どなたかわかる方教えてください。よろしく御願いします。

  • 実践的な遺伝子的アルゴリズムの作成法

    素人ですが、遺伝子的アルゴリズムを考える上で、大きな問題に直面しています。 1)最適化の対象を如何にコーディングするか? 2)交叉点を如何に設けるか? これらは組合せの対象の要素間に何らかの曖昧な複数の相関関係がある場合に難しくなります。 そこで、 1)「遺伝子的アルゴリズム」をタイトルにした一般の技術系の和書に書かれている以外に、実例を調べる手段? 2)社会人が遺伝子的アルゴリズムの開発の実際を学ぶための公共の機関、例えば聴講生として学べる場所? 3)遺伝子的アルゴリズムを組み込んだソフトを作る上で、普段使用しているC++などの汎用プログラム言語と、SchemaやLISPなどの知能プログラミング言語とでは、どちらが便利なのでしょうか? これらの人工知能プログラム言語には、コーディングや交叉のための専用のコマンドが提供されているのでしょうか? 自分は、情報工学の出身ではないため、C++言語と「遺伝子的アルゴリズム」の技術書籍以外には、バックグラウンドがありません。よろしくお願いいたします。

  • エクセルのデータ分析における相関について

    いつもお世話になっております。 添付ファイルのような表を作成して、それぞれの相関を調べたいと思っております。 エクセルのデータ分析で相関係数の表を出力すると、大半が0.2以下となり相関が弱いという結果になりました。 この結果に『あれ?こんなに相関ないの?』っと疑問を感じおります・・・! (1)データ分析の相関において元となる表の空欄の扱いはどうなるのでしょうか?  ※作成した表では、各セルに数式をいれており、ゼロ値を非表示設定にしてあるため、表示設定にすると、空欄部分は0が表示されます。   作成した表の本質は空欄部分はゼロではなく、データ無という扱いです。    この場合、相関係数を算出すると、ゼロ値として計算されるのでしょうか?       データ無という扱いにする場合は、どうすればよいのでしょうか?(例:NA()でエラーにするとか?) (2)データ欠損となる場合の処理は、  例えば、A1~J1まで10個のデータがあり、うち5個が空欄(データ無)の場合は、どのような処理になるのでしょうか? 分かりづらい文章で申し訳ありませんが、よろしくお願いいたします。