プログラミング上達したい人が書くブログ

プログラミング上達したい人が書くブログ

主に、アニメやPython、C++、競技プログラミング(初心者)について書きたいです。また、1週間に一つの記事を心掛けています。学生です。備忘録と書かれたものは他人に見せることを考えて書いてないため見にくいです。

Neural Network Consoleを使ってみた Part3

はじめに

 前回のパートで書いた通り、今回も正確性を挙げるためにいろいろ試していきたいと思います。

 後、これから2週間忙しく投稿できなくなるため、二つ投稿しておきます。

 

やってみたこと その3

 落ち着いて考えた結果、なぜ前回Confusion Matrixが表示されなかったのかわかった気がします。それは、なぜか結果の総和が1になっていなかったからです。レイヤーリファレンスリファレンスにはSoftmax+CategoricalCrossEntropyと等価であり、Softmaxは総和が1になるよう出力値を調整していると書いてあるはずなのに、なぜこうなるのかよくわからないです。そこで、今回はその反省点を踏まえて変更しました。その設計図が以下のようになります。

f:id:sachishimei:20170906205034p:plain

そうです。これ、実質Softmaxの2枚掛けになります。そして、結果が以下のようになります。

f:id:sachishimei:20170906205242p:plain

出ました。やっぱり理由はその部分のようです。ただ、結果は誤認識が増えてしまい正確性が下がりました。もうこれどうすればいいんでしょうか。

 

やってみたこと その4

  Affineという基本レイヤ―を使うのではなく、畳み込み積分を用いたConvolusionという基本レイヤ―を使ってみました。設計図は以下のようになります。

f:id:sachishimei:20170908104749p:plain

 これで、トレーニングしようとしたのですができませんでした。エラーの内容は「ValueError: could not broadcast input array from shape (64,1) into shape (64,1,24,24)」となっていて、たぶんパラメータの設定が間違っているんだろうという予測はつくのですが、畳み込み積分そのものがよくわからないためわからないのが現状です。ちなみにパラメータは以下のようになります。

f:id:sachishimei:20170908105153p:plain

 

終わりに

 ちょっとできない理由が分からないため、畳み込み積分についてちょって勉強してみます。そして、エラーのとり方が分かったらまた記事を出したいと思います。つまり、それまでは、この画像認識についてはお休みになると思います。

 また、理由が分かる方は連絡くださると助かります。

 

Neural Network Consoleを使ってみた Part2

前記事URL

printf.hatenablog.com

今回やってみたこと

 前回の記事の評価の正確性が92.85%でしたが、それについて正確性を挙げる方法について試してみました。

やってみたこと その1

 Affineを二つに増やし、もともと1層のニューラルネットワークを2層にしてみました。設計図は以下のようになります。

f:id:sachishimei:20170902193940p:plain

そして結果は以下のようになります。

f:id:sachishimei:20170902194254p:plain

減ってる...?理由が分かりません

やってみたこと その2

 SoftmaxCrossEntropyというレイヤーを使ってみました。SoftmaxCrossEntropyとは、レイヤーリファレンスを引用すると、

blog.dl.sony.com

 カテゴリIndexで与えられるデータセットの変数との相互情報量を最小化するニューラルネットワークの出力層です。SoftmaxCrossEntropyはSoftmax+CategoricalCrossEntropyと等価ですが、まとめて演算することにより演算誤差を抑える効果があります。プロパティはSquaredErrorと共通です。

となっています。私が注目したところは、Softmax+CategoricalCrossEntropyと等価であり、一緒に計算することで誤差が小さくなることです。

 設計図は以下のようになります。

f:id:sachishimei:20170905215911p:plain

 そして、結果は以下のようになりました。

f:id:sachishimei:20170905215954p:plain

 あれ?何にも出ていない!すいません、理由が分かりませんでした。知っている方いたらコメントしていただけると助かります。出たばっかりのIDEのため情報が少なく、調べても出てきませんでした。でも、下に貼られている結果を見る限りは、ラベルと一緒の値が一番高くなっているし判定はうまくいっているのかと思います。

f:id:sachishimei:20170905220500p:plain

 

中間休憩です。

 ちょっと行き詰ってしまったため、今回はここで終わりにしておきます。次回も同じように、確率が上がらないか試していくつもりです。よろしくお願いします。

 また、学生であり至らぬ点も多いことを思います。何かありましたらコメントいただけると助かります。

Neural Network Consoleを使ってみた Part1

はじめに

 このページは、ニューラルネットワークについて無知な私が、「ニューラルネットワークコンソールを使えば効率的な学習ができる」という謳い文句に誘われて、ニューラルネットワークについてこのIDE(統合開発環境)を使って学んでいこうとするページです。

ニューラルネットワークって?

www.slideshare.net

私は上記のスライドで簡単な部分は学びました。

ニューラルネットワークコンソールって?

 説明されている公式サイトは以下のようになります。

www.sonynetwork.co.jp

 上記サイトの内容をまとめると、「このIDEは、GUI的な操作でニューラルネットワークの設計ができるんだ」ということです。

 ちなみに配布サイトは以下のリンクに貼っておきます。

dl.sony.com

このページではなにをするのか?

 とりあえず0-9までの文字を判定していこうと思います。

はじめに読んでおくべきこと

blog.dl.sony.com

上記リンクのチュートリアルは読んでおくべきです。これは、サンプルプログラムを実行するまでの一連の流れが書いてあり便利です(初心者感)。また、上記リンクのサイトには簡単な使い方が書かれたページもあり、初めての方はとても便利です。

 

作った設計図

f:id:sachishimei:20170901201416p:plain

 設計図は上図になります。Inputに使うDatasetは、ニューラルネットワークコンソールをインストールしたときに付属しているmnist_training.csvを使っています。また、評価用のデータには、mnist_test.csvを使っています。

 Affineとは、リファレンスから引用させてもらうと、

全ての入力値から、OutShapeプロパティで指定する全ての出力ニューロンへの結合を持つ全結合層です。

 

o = Wi+b

(iは入力、oは出力、Wは重み、bはバイアス項を示す)

といったことが書かれています。OutShapeプロパティとは、出力ニューロン数のことです。つまり、ニューラルネットワークでいう隠れ層の第1層目であるということです。

 Softmaxとは、Activationレイヤーと言われ、いわゆる活性化関数の1種です。これもまた、引用させてもらうと、

入力値のSoftmax値を出力します。カテゴリ分類問題における確率など、0.0~1.0かつ合計が1.0となる出力値を得たい場合に使用します。

 

ox=exp(ix) / Σ_jexp(ij)

(oは出力、iは入力、xはデータのIndexを示す)

と書かれています。私も詳しい理論はわかりませんが、カテゴリ分類問題に使うことができると書かれているためこれを用いさせてもらいました。

 CategoricalEntropyとは、ロスレイヤーと言われ、いわゆる出力層です。これは、正解データとの相互情報量を最小化する機能を持っています。

 

トレーニングしてみた結果

結果は以下のようになりました。なるほどわからん。とりあえずエラー(赤い線)とコスト(青い線)の値が右に進むごとに減っていればよいということですが、なぜかVALIDATION ERROR(赤い点線)が増えていて成功してるのか不明です。

f:id:sachishimei:20170902112444p:plain

評価用データを用いて成功率を見てみた。

以下の画像のAccuracyが、成功率を表しています。これによると、約92%のデータがうまく分類できているようです。これは、成功していると言っていいのでは?

f:id:sachishimei:20170902113323p:plain

これからのこと

 とりあえずどうやったら成功率が上がるのかを確かめてみようと思います。また、これはPythonソースコードで受け取れるのかもわかりませんし、そこも知りたいです。

 もっとニューラルネットワークコンソールをいじってみたいのですが、テストデータしかないためなかなかできません。だれか、そういうテストデータとして使えるようなサイトを知りませんか?例えば、リンゴの画像データをまとめてダウンロードできるようなサイトです。知っていたら、コメントしていただけると助かります。

AtCorder Regular Contest 082 を受けた感想

筆者の結果

AtCoder Regular Contest 082 - AtCoder

E問題無理。

C問題解法について

 

 ソースコードは以下のようになります。

 考えた解き方としては、ある数字の個数と前後数字の個数を足した数の最大値が答えとなると考えました。例えば、入力が1 3 5 8 2 7 7 6としたとき、1-3の個数が3、2-4の個数が2、...、6-8の個数が4となり、最大値が4となり最終的な答えが4となります。

 ソースコードの内容として、配列nは、それぞれの数字の個数を入れる役割を果たしています。例えば、5の個数であればa[5]の値で表します。

 最初のfor文は入力部分です。vector配列aに入力値を入れている。

 次のfor文では、値を調べてその値の個数に1足している。*よく考えたら、この部分入力部分でもできるから実質無駄なことしてます。

 それ以降のソースコードでは、毎回連なっている3つのnの足した数をもとめて、それの最大値を出しています。

#include<iostream>
#include<vector>

using namespace std;

int main(){

  vector <int> a;
  int N,b;
  int num[100000] = {0};
  cin >> N;
  for(int i = 0;i < N;i++){
    cin >> b;
    a.push_back(b);
  }
  for(int i = 0;i < N;i++){
    num[a[i]]++;
  }

  int max = num[0]+num[1]+num[2];
  for(int i = 1;i < 99998;i++){
    int m;
    m = num[i]+num[i+1]+num[i+2];
    if(max < m){
      max = m;
    }
  }

  cout << max << endl;
  
}

 

D問題解法について

 ソースコードは以下に張り付けておきます。はい、長いです。申し訳ありません。

 考え方としては、「pi = i」となるものが1つ続いているか、2つ続いているか、3つ続いているかに分けているものです。

 例えば、入力が1 3 2であった場合続いているものは1つなので、次のやつと入れ替えればいいのです。また、入力が1 2 4 3のときは、2つ続いていますが、これも1と2を入れ替えればいいのです。では、入力が1 2 3のときはどうするかというと、2回適当に入れ替えれば大丈夫です。

  このように、各部分をパターン認識のような考え方をして回数を求めました。

  ソースコードを解説すると、ごり押ししてます。if文1個続いたら、2個続いたら、3個続いたら、ほかには見たいな感じに場合分けしています。注意すべきは、問題が1から始まるのに対して、配列が0から始まることです。

 

#include<;iostream>
#include<algorithm>
#include<vector>

using namespace std;

int main(){
  vector <int> a;

  int N;
  cin >> N;
  for(int i = 0;i < N;i++){
    int b;
    cin >> b;
    a.push_back(b);
  }
  int sum = 0;
  for(int i = 0;i < N;i++){
    if(a[i] == i+1){
      if(a[i+1] == i+2){
	if((a[i+2] == i+3) && (a[i+3] != i+4)){
	  sum = sum+2;
	  int swap;
	  swap = a[i];
	  a[i] = a[i+1];
	  a[i+1] = swap;
	  swap = a[i+1];
	  a[i+1] = a[i+2];
	  a[i+2] = swap;
	  i = i + 2;
	  
	}
	
	else{
	  int swap;
	  swap = a[i];
	  a[i] = a[i+1];
	  a[i+1] = swap;
	  sum++;
	  i++;

	}
      }
      else{
	int swap;
	swap = a[i];
	a[i] = a[i+1];
	a[i+1] = swap;
	sum++;
	i++;

      }
    }
  }
  
  cout << sum << endl;

}

今回の感想

 とにかくE問題レベルになると全く解けなくなります。550点くらいの問題を出してほしい...

Python使って株で楽して生きたい人生だった... 

はじめに

 楽して金を稼ぎたいと思ったけど、現実ではだめったったよという人のページです。ニートみたいな生活がしたいなあ... 

 

今回使ったライブラリ

 今回使ったライブラリは以下のようになります。

  • scikit-learn

 言わずと知れた機械学習ライブラリです。様々な機械学習に対応していて、今回は、そのなかの回帰直線とSVM(サポートベクターマシーン)を用いています。

  • numpy

 数値計算ライブラリです。これを使うことで行列の計算が容易にできます。

  • pandas

 今回は、データ収集のためにCSVファイルを使うため入れています。

  • pandas_datareader

 yahooやGoogleFinanceから企業の株価などを取得できるが、なんかできなかった

 yahooAPIが現在よろしくないらしいです。

 

今回の主な方針

 まず、説明変数には「終値」と、「後10日分の終値を用いて作った回帰直線の回帰係数」を用いています。

 理由としては、今回株をどのようにとらえるかに起因します。私は、株価の推移を波だととらえ、波であればある点の接線の傾きを求めれば、下がる瞬間が事前に分かることになると考えました。しかし、当然株価を数式として微分することはできません。そこで考えたものが回帰直線です。これを使うことで接線のようなものが取れると考えました。

 そして、目的変数には次の日の株価が上がるか下がるかを使っています。

データを取得してみる

CSVファイルでの取得は株価データサイト k-db.comでできます。

また、CSVファイルを読み込んで、その中から終値を取り出す部分のソースコードは以下のようになる。また、kabutest2_1.csvで株価のデータは保存しています。

as_matrix()でNumpyのarrayで使えるようにしています。

df = pd.read_csv("kabutest2_1.csv",encoding = 'cp932')
x1 = df["終値"].as_matrix()
 

 目的変数と説明変数を作ってみる

 まず、目的関数の一つである終値の値は、上記ですでに完了しています。そこで、残りをmake(f)という関数をつくって作成しました。その中の、回帰係数を求める部分のソースコードが以下のようになります。

 ソースコードの内容は、まず、後10日分の終値を用いて回帰直線を作るうえで、最初の10日間はデータの個数が10個以下のため、前の日の終値を含めたもので回帰直線を作っています。そして、「clf.coef_」が回帰係数を表しています。最初の「for」がこれに対応しています。また、最初の2日間は回帰直線すら作れないため3日目に作ったものを「配列a」に入れています。

 次の「for」は、10日分のデータを用いて回帰直線を作り、「配列a」に追加しています。追加するためには、np.append()で使うことができます。

    a = np.array([])
  #ここでいうfは、終値の配列、つまり上記のx1のことである。 for n in range(2,10): x = f[0:n] time = np.arange(n) time = time.reshape(-1,1) x = x.reshape(-1,1) clf = linear_model.LinearRegression() clf.fit(time,x) if n == 2: a = np.append(a,clf.coef_) a = np.append(a,clf.coef_) a = np.append(a,clf.coef_) for n in range(10,f.shape[0]): x = f[n-10:n] time = np.arange(n-10,n) time = time.reshape(-1,1) x = x.reshape(-1,1) clf = linear_model.LinearRegression() clf.fit(time,x) a = np.append(a,clf.coef_)

 

 以下のソースコードは、make関数内の目的変数を作る部分である。内容は、次の日のデータが上がったときにに目的変数の配列に1を代入、逆に下がったときに0を代入するものです。ただ、最後の日が分からなかったため、1をとりあえず入れときました。

また、最後のreturnで説明変数の一部である回帰係数を入れた配列aと目的変数であるbを戻り値としています。

    b = np.array([])
    for n in range(0,f.shape[0]-1):
        if f[n] <= f[n+1]:
            b = np.append(b,1)
        else:
            b = np.append(b,-1)
    b = np.append(b,1)

    return a,b

 

 以下のソースコードはメイン関数内のものです。これは、上部で作ったa,bをそれぞれx2,yに入れています。そして、回帰係数が次の日のほうが高かった場合は、x3に1を入れていて、下がった場合は-1を入れています。

x2,y = makex1(x1)
x3 = np.array([])
for n in range(0,x2.shape[0]-1):
    if x2[n] <= x2[n+1]:
        x3 = np.append(x3,1)
    else:
        x3 = np.append(x3,-1)
    x3 = np.append(x3,1)

これで、目的変数と説明変数の原型が完成です。今回のプログラムでは目的変数にy、説明変数にx1とx3を使います。

 

説明変数を一つの配列にまとめる

よく仕組みはわかりません。とりあえず「Python 行列の連結」で調べました。

x = np.empty((0,2), float)
for nm in range(0,x1.shape[0]):
    d = [x1[nm],x3[nm]]
    x = np.append(x,np.array([d]),axis = 0)

 

SVCを使って機械学習とそれを用いて予測を行う

  予測に使うテストデータを用意するのがめんどくさかったため作ったxとyの最後尾10個のデータを使うことにしました。よって、機械学習させるとき、ranを作ってスライスを使っています。

 predictedには予測した結果を入れています。

clf = svm.SVC(gamma = 0.01, C = 100)
ran = x.shape[0]-10
test = x[ran:ran+10]
clf.fit(x[:ran],y[:ran])

predicted = clf.predict(test)

 

結果の表示部分

表示したソースコードは以下になります。

print(y[ran:ran+10])
print(predicted)

 

実行結果

 ええ。全然違います。ちなみに上が実際のデータでしたが予測されたデータです。

[ 1.  1. -1.  1.  1.  1.  1. -1.  1.  1.]
[-1. -1. -1. -1. -1. -1.  1.  1. -1. -1.]

 

終わりに

 結局どうすればええんや...。別のデータでやったときは8割の成功率だったから結局平均すると5割に落ち着くのかなあ。なにかこれを読めばよいという書籍などがあったら教えてほしいです。