情報学部大学生のダラダラ日記

β日記

機械学習や日記っぽいものを書きます

ソフトマックス(SoftMax)関数についてまとめてPythonで実装してみる。

はじめに

 筆者は機械学習についての知見が全くありません。なので特に機械学習の論理について誤った解釈をしていると思いますので、後々勉強して適宜訂正していこうと思います。

ソフトマックス関数とは

 以下、wikipediaからの引用。

K 個のクラスに分類する。出力は K 個で、総和は 1 であり、そのクラスに所属する確率と解釈する。 は 0 または 1 もしくは確率で、n 番目の訓練データがクラス k に所属する時 1。 。交差エントロピーを使用している。この活性化関数はソフトマックス関数と呼ばれる。

活性化関数:
引用元:活性化関数 

  ありがとうwikiさん。ざっくり解釈だと幾つかの大小様々な実数を足して1.0になるような実数に変えてくれる関数だと思います。

式をもう少し簡単に書くと

x = [x0,x1,x2,...,xn]

u = exp(x0)+exp(x1)+exp(x2)+...+exp(en)

y0 = exp(x0)/u , y1 = exp(x1)/u , y2 = exp(x2)/u , .... ,yn = exp(xn)/u 

y = [y0,y1,y2,...,yn] 

n次元の実数ベクトルxを受け取り、n次元実数ベクトルyを返します。

確率なので当然

y_sum = y0 + y1 + y2 + ... = 1

0 < yi < 1

となります。

いつ使うのか

 書いた文字が「め」か「ぬ」を判別するプログラムがあるとし、ある手書き文字が入力された時にソフトマックス関数が存在しない場合、「め:3.0、ぬ:3.5」などと出力されます(多分)。そこでこの入力文字がなんなのかと確率で表すためにソフトマックス関数を用いると「め:0.3775...、ぬ:0.6224..」と表示されます。つまり「め」が約38%、「ぬ」が約62%という風になります。This is ぬ.

↓↓ここからただの筆者の推測なので流し読みしてください↓↓

 しかし、ただ確率を提示するだけならば3/(3+3.5) ≒ 0.46、3.5/6.5 ≒ 0.53となり、同様に確率を生成することができます。なぜソフトマックス関数が使われているのか考えました。それは数式を見ただけなのですが、expを使って確率を生成することでより明確に確率に差が生まれます。ソフトマックス関数を使った場合、4:6ほどの確率になったのに対しただの確率計算だとほぼ5:5となっています。他にも例えば「め:1.0、ぬ:9.0」であった場合、普通の確率計算の場合「め」である確率が10%だと出力されます。しかしソフトマックス関数を用いると「め」である確率は約3.35×10^-4となりほぼ0%です。このような理由でソフトマックス関数が用いられているのだなと勝手に解釈しました。あとは負の出力であっても確率に直すことができるところ、とか。

↑↑ここまで↑↑

実際にプログラムを書いて動かしてみる

まずは素直に定義通り

import numpy as np

def softmax(a):
    x = np.exp(a)
    u = np.sum(x)
    return x/u

b = np.array([1,2,3])
y = softmax(b)
print(y)

出力

[0.09003057 0.24472847 0.66524096]

 指数関数は怖いのでオーバーフロー対策をします。

import numpy as np

def softmax(a):
    a_max = max(a)
    x = np.exp(a-a_max)
    u = np.sum(x)
    return x/u

b = np.array([100000,100001,100002])
y = softmax(b)
print(y)

出力

[0.09003057 0.24472847 0.66524096]

 配列の最大値を各要素から引くことですべて0または負となります。なぜこのプログラムで上記と同様の出力結果となるのかは紙に書き起こせばわかると思います。

まとめ

 今回は、初めて聞いたソフトマックス関数についてまとめてみました。これから実際に開発していくにつれて当然のように扱う関数だと思うので早めに学んでおいてよかったです。しかしイマイチ理解が浮ついているのでそこは実際に使用しながら理解できたらなと思っています。

 

参考文献↓

qiita.com

 

 

 

おわり。

もしよければ↓ぽちっと↓お願いします。

ブログランキング・にほんブログ村へにほんブログ村 PVアクセスランキング にほんブログ村

【Python3】Numpy配列の要素の合計を求める時にベクトルの内積を使うと速くなるらしい

はじめに

  Σ計算がfor文のようなものであることはご存じだと思いますが、ただでさえPythonは遅いので素直にfor文でまわしていたら大きなデータの時に多くの時間を要してしまいます。参考書によるとfor文よりも内積使った方が速いらしいです。要素の合計といえばNumpyのsum関数があるので、それも含めた3種類で比較してみました。具体的な内積の考え方は後述します。自分の予想としてはsum関数がなんだかんだ一番速いと思います。根拠はないです。

プログラム

 

#for文

    
import numpy as np
import time

for i in range(10):
    a = 0
    c = np.linspace(2,10000000,5000000)

    t1 = time.time()
    for j in c:
        a = a + int(j)
    print(a)
    t2 = time.time()
    t = t2 - t1
    print(t)
#sum関数

import numpy as np
import time

for i in range(10):
    c = np.linspace(2,10000000,5000000)

    t1 = time.time()
    print(sum(c))
    t2 = time.time()
    t = t2 - t1
    print(t)
#内積

import numpy as np
import time

for i in range(10):
    c = np.linspace(2,10000000,5000000)

    t1 = time.time()
    d = np.ones(5000000)
    print(np.dot(c,d))
    t2 = time.time()
    t = t2 - t1
    print(t)

 今回扱った配列はlinspaceで用意しています。2から10000000を5000000等分した等差数列となっています。time関数がたまーに機能しなくなるので逐一出力させています。ついでに合計も。for文のプログラムは配列の要素を1つ1つ読み込んで足しています。sum関数は引数に配列ぶっこむだけです。そして問題の内積さん。Numpy配列はベクトルであるため要素が全て1のベクトルを用意し、合計を求めたい配列(ベクトル)との内積をとるだけです。ベクトルの内積は各要素の積を足したスカラー量であるのでこの場合のベクトルの内積は配列の合計と等しいことがわかります。np.dot(a,b)でaとbの内積を求めます。

実行結果(合計値は正しく出力されていたので省略)

 

#for文
1.229989767074585
1.1679975986480713
1.2129971981048584
1.244002342224121
1.2080466747283936
1.2040400505065918
1.171039342880249
1.190033197402954
1.4729993343353271
1.1989998817443848
#sum関数
0.663999080657959
0.5890030860900879
0.4519975185394287
0.44500064849853516
0.4510006904602051
0.43799757957458496
0.5030021667480469
0.464000940322876
0.45798826217651367
0.44900035858154297
#内積
0.03200030326843262
0.030002832412719727
0.029001474380493164
0.029003143310546875
0.029993057250976562
0.031000137329101562
0.030005216598510742
0.02900385856628418
0.03000187873840332
0.03100109100341797

 最後に

 まず、実行結果はAverageを取る必要がないほど明確に内積<sum<forとなりました。しかも割と大差がつきました。この結果だけ見て一概に内積の処理が高速かと言われればそうではなく、要素数が少ないとsumの方が速くなったりもしました。どのような時にsumの方が高速であるかなどは要素数を変えて実験する必要があります。僕はやりません。なぜ内積の方が速くなるのか考えたのですが、全くわからなかったので教えていただきたいです。

 今回のような意外なアプローチができるから数学はおもしろいですね。大きなデータを扱うようなPythonプログラマならば知っておいて損はないと思います。参考書の何気ない一文にほんまか!?と疑って検証しようと思ったばかりに多くの時間を費やしましたが知見が広がったのでよしとします。

おわり。参考書↓↓

 

 

 

もしよければ↓ぽちっと↓お願いします。

ブログランキング・にほんブログ村へにほんブログ村 PVアクセスランキング にほんブログ村

LaravelのみでJavascriptを使わずにいいね機能を作ってみた

はじめに

 いいね機能をJavascriptを使わずに実装したい(jsやったことないから逃げたい)ので自分で考えて実装してみました。絶対にもっと効率のいい方法あるので教えてほしい。

 ※Laravel 6.0

設計

・いいねしている時はいいね削除ボタン、いいねしていないときにはいいねボタンを表示する。

・ユーザがログインしている時のみいいねボタンを表示する。(今回は割愛)

php(Laravel)のみを用いて実装

プログラム(コントローラ)

FavoriteController.php(一部)
    
    
    public function favorite(Request $request){

        $twe_id = $request->twe_id;

        $name = DB::table('post')->where('twe_id', $twe_id)->first();

        $names = $name->user_id;

        $user = Auth::user();

        $favname = $user['name'];

        $judge = DB::select('select * from favorite where twe_id = ? and fav_name = ?', [$twe_id, $favname]);



        if(!$judge){

            DB::insert('insert into favorite (twe_id, fav_name, name) values (?,?,?)',[$twe_id,$favname,$names]);            

        }else{

            DB::delete('delete from favorite where twe_id = ? and fav_name = ?',[$twe_id,$favname]);     

        }

        return redirect()->back()->withInput();

    }

プログラム(ビュー)

Home.blade.php(一部)

    @php
        $count = 0;
    @endphp
    
    @if(Auth::check())
    <form action="{{ url('/fav/' . $d->twe_id) }}" method="POST">
    {{ csrf_field() }} 
    @foreach($judge as $j) 
        @if($j->twe_id == $d->twe_id) 
            @php 
                $count = 1; 
            @endphp 
        @else 
            @php 
                $count = $count; 
            @endphp 
        @endif 
    @endforeach 
    
    @if($count == 1)
        <button class="btn btn-warning" style="float: right;">unlike

@else <button class="btn btn-success" style="float: right;">Like

@endif

解説

 DBの設計などを省略しているため、概要のみの解説。 

 まず、ビュー側のいいねボタン(いいね取り消しボタン)をクリックした時、いいねしたい投稿のidをPOST送信する。そしてコントローラでリクエストを受け取り、$twe_idに格納する。次に、$userにAuth::user()でログイン中のユーザ情報つまりいいねするユーザ情報を格納する。そして$fav_nameにそのユーザのidのみ格納する。

 次にそのユーザがその投稿に既にいいねしているか否かでいいねテーブルに格納するか削除するかを判断しなくてはならない。$judgeという変数にいいねテーブルからそのユーザかつその投稿idのデータをselect文で抽出し、存在しないならば新しくいいねテーブルに追加、存在するならばそのデータを削除する。そして元いたページにリダイレクトする。

 つぎにフロント側の解説をする。いいね済か否かを判断する変数$countを用意する。$d->twe_idが現在表示している投稿のid、$j->twe_idには現在ログイン中のユーザがいいねしている投稿のidが格納されている。つまりこの2つが一致した時にいいねしているということなのでいいね取り消しボタン、そうでないときにいいねボタンを表示する。ここで直接ボタン表示をif文の中に入れると処理をfor文でまわしているため何個もボタンが表示されてしまう。ゆえに変数$countを用意した。

 おわり。

 

 

もしよければ↓ぽちっと↓お願いします。

ブログランキング・にほんブログ村へにほんブログ村 PVアクセスランキング にほんブログ村

 

Laravelの導入したてで500エラーが出た

はじめに

 Laravel勉強すっぞ!!composerからlaravel入れてフレームワークとはなんぞやっての勉強していざ実践!って時に

卍500エラー卍

 これまで大学の実験とか日常生活で400何番とか300何番とかは見たことあったけど500エラーは初見です。お恥ずかしながら。

500エラーについて

 ざっくりした解説だとWebサーバ側が"なんか"おかしいぞって伝えているエラー。具体的にこれという原因があるわけではなくたとえば.htaccessの記載が間違っていたりApacheの記載が間違っていたりと色々。

 本題となるこの場合どうすればよいかを記載する。参考にしたというか解決策そのまま書いてくださったサイトを以下に示す。

殺意!Laravelを初期導入したら500エラーが出た件! │ Traveler

今回の場合の解決策

 なぜエラーが起こったのかなどは上のサイトを観てください。Windowsで行っていたためまず作業ディレクトリを開き、ファイル→Windows PowerShellを開く。そして

f:id:Parco1021:20190911182445p:plain

上のようにコマンドを入力すると…

f:id:Parco1021:20190911183219p:plain

解決!!

最後に

 参考にできたサイトがあったからよかったものの、なんでエラーが吐かれたのか、上のコマンドを入力するとなおったのかが未だにわからない。わかる人いたら教えていただきたいです。

 

 

実験の結果と考察~心理学実験をやった話③~

はじめに

 今回は実験の結果と考察について書いていこうと思っています。流れはデータの説明→全データの考察です。前回↓↓

parco1021.hatenablog.com

 使用ツール

・Psychopy3

・Python3

Arduino

データの説明

f:id:Parco1021:20190904200653p:plain

 考察するためにグラフとして4つ用意した。〇-△となっているが、〇のBがボタン押し条件、Vが振動条件であり、△のAが音、Vが図、AVが両方である。

 まず、左上のグラフについて説明する。横軸を実際の遅延、縦軸を実験参加者からの報告値とした。そして見やすさのためにy=xを用意した。つまりy=xより下ならば実際よりも早く知覚されている。例えば、実際は400msなのに300msだと知覚している。この実験参加者は振動条件の音と図両方提示はほぼ正確な値を報告しているが、全体としては早めに知覚しているということである。

 次に、右上のグラフについて説明する。右上は実際の値-報告の値を縦軸にとっている。つまり負であるならば早めに知覚しているということである。左上のグラフをより実際の値と報告値の差を見やすくする目的がある。

  次に、左下のグラフについて説明する。右上のグラフを各条件について平均をとったものを棒グラフにしたものである。つまりどの条件がどれだけ実際値と報告値に差があるかを見やすくすることが目的である。この実験参加者は特にボタン条件の時、差があることがわかる。

 最後に、右下のグラフについて説明する。右下のグラフが今回の実験の主たる目的のIBの強さを表すグラフである。右上のグラフのV-XからB-X(X={A,V,AV})をひいたものである。Vは振動条件であるので意図無し、Bはボタン条件なので意図有りであるため、縦軸が正である時、意図が無い方が遅く知覚されているということであるためIBが生じているといえる。この実験参加者はV以外では概ね正となっているためIBが生じている。

 以上がグラフの説明である。本質的な部分をみるためには左上と右下だけで良いのだが、右上や左下のグラフのように多面的にデータを観測することで外れ値や、より具体的に考察することができる。一つまた勉強になった。

全体データと考察

f:id:Parco1021:20190904204524p:plain

 全体のデータが上の通り。思ったよりデータ綺麗になってうれしい(?)。まずは結果からわかることを挙げる。

・全体として早めに知覚されている。

・実際値と報告値の差は実際値が大きくなるにつれて大きくなっている。

・Bの方がVよりも差が大きい。

・音が最も差が大きく知覚されている。

・しかし、IBの大きさは第二条件による差はない

・いずれの条件でもIBは生じている。

  まず、いずれの場合もIBが生じていることについてさすがに仮説通りでよかった。これ間違ってたらIB…ってなっちゃう。次に、第二条件で差がないことについて、そもそもの仮説の前提条件である視覚よりも聴覚の方が反応時間は早いから注意力が云々が間違っていたことが考えられる。反応時間によるIBへの影響がないことがここから考えられる。

まとめと感想

 実験を0から自分で企画、実践、解析までやったのは本当にいい経験だし今しかできないなって思った。担当教授曰く、B4の方達よりもよく取り組んでいるとの言葉をいただいたのでとても嬉しかった。この実験をやるまでPythonに触れたことすらなかったのでとても苦労した。一番苦労したのはArduinoとのシリアル通信。

parco1021.hatenablog.com

 実験の有用性を聞かれても直接的には考えられない。しかし、IB自体は多くのことに応用できると思った。意図の有無で体感時間が変わることをモデリングすることで何か役に立つことがあると思う。思い浮かばないけど!何かあったら教えてください。

 これで実験の話は終わりです。もしここまで読んでくださった方いたらありがとうございました。一応時間に余裕できたら今回の実験のプログラムの説明もやりたいな。

 

 

 

Comunicaç o serial com  Python e Arduino (Portuguese Edition)
 

 

もしよければ↓ぽちっと↓お願いします。

ブログランキング・にほんブログ村へにほんブログ村 PVアクセスランキング にほんブログ村

実験の仮説と実験方法~心理学実験をやった話②~

はじめに

 本ブログは前回の続きである。実験に関わる用語は前回の記事を参照してください。

 

 

parco1021.hatenablog.com

 

実験の仮説まで

 IBについて実験しよう~ってなっても既知であるものを実験したとしても意味がない。既知であるものとして例としては意図の強さを比較してより意図の強い場合とそうでない場合を比較し、より意図が強く働く方がIBが強くなることがわかっている。ここで、IBの強さを以下のように定義する。

(IBの強さ) = (意図がない体感時間) - (意図がある体感時間)

つまり、意図がある方が短く感じられることがIBであるため正である時にIBが生じていると言うことができ、IBの強さは正に大きくなるほど強くなる。

 私はこういった先行研究から異なる知覚間でIBの強さは異なるのかを実験しようと考えた。今回、視覚と聴覚を比較することにした。視覚と聴覚は視覚の方が反応時間は早い。そこから視覚の方がIBは強まるすなわち意図がある時に早く知覚されると仮説をたてた。

実験の方法

 実際に私が行った実験の方法を説明する。実験参加者として大学生男女10名を対象とした。参加者を集めるのにめttttttっちゃ苦労した。そりゃつまらんし誰もやりたいなんて思わないよね。参加者のみなさん本当にありがとうございました。

 

 

 

f:id:Parco1021:20190902212204p:plain

f:id:Parco1021:20190902212158p:plain

上の振動条件が意図無し、ボタン押し条件が意図ありです。ボタンor振動の後に0~1000ms(1s)のランダムな時間があり、図が提示されるか音が出るかその両方が出るかが第二イベントとしてある。このランダムな時間を参加者に推定してもらう。そして両者に差があるのか、そして第二イベントによる差はあるのかを実験によって調査する。

さいごに

うーん…実験方法についてもっと書きたいんだけどあんま書いてもな…って感じでめっちゃ短くなっちゃった。まあこれでヨシ。次は実験結果と考察をまとめるよ。

次回↓↓

 

 

 

 

もしよければ↓ぽちっと↓お願いします。

ブログランキング・にほんブログ村へにほんブログ村 PVアクセスランキング にほんブログ村

インテンショナルバインディングとは~心理学実験をやった話①~

 

どんなことを実験したのか

 一口に心理学実験と言っても多くの種類があります。僕自身最初は睡眠についての何かをしたいと思っていたのですが、手間がとてもかかり、学部生ではとても実験までたどり着く事ができないそうなので方針を変え、2つの知覚(視覚や聴覚、触覚など)の関連性について学ぼうと考え、教授からインテンショナルバインディング(IB)について調べるのはどうかとの提案をいただきました。

 

インテンショナルバインディング(IB)とは

 英語で書くとIntentional Bindingとなり、意図による束縛のような感じの意味です。勉強するにあたって読んだ文献を下に幾つか貼っておきます。

 

www.jstage.jst.go.jp

charbonniers.org

 

 オリジナル実験において、まずオペランド条件とベースライン条件を以下のように定義します。

オペランド条件…手元にあるボタンを押すまたはボタンを押してから250ms後に音がなるのでその音が鳴った時の時計の針の位置を報告

・ベースライン条件…手元にあるボタンを押すまたは突然音が鳴るので音が鳴った時の時計の針の位置を報告

この2条件に分かれて時計の針の位置をそれぞれ報告させたところ、行為(ボタン押し)のタイミングはオペランド条件の方がベースライン条件よりも遅く知覚され、音刺激のタイミングはオペランド条件の方がベースライン条件よりも早く知覚された。図示すると以下のようになる。青が時間軸で赤がベースライン条件、黄がオペランド条件である。

f:id:Parco1021:20190831204313p:plain

 この図からオペランド条件の方がベースライン条件よりも短く知覚されていることがわかる。また、オペランド条件とベースライン条件の違いとして、オペランド条件は音が鳴るタイミングがある程度わかる⇒自分の行為と音に因果関係があるように感じられるため自分が音を鳴らしているかのように感じられることである。その反面ベースライン条件にはそういった意図はなく、突然音が鳴る。つまり両条件の違いは意図の有無である。

 ざっくり説明すると「意図がある時とない時で体感時間が変わるで」ってことです。何言ってるかわからんと思います。僕もわかりません。うそですわかります。

さいごに

 みなさんの身近でもこれは感じられていることです。多くの現象が考えられますが、例えば楽しいことってつまらないことより短く感じられませんか?この現象についてはIBだけではなく多くの原因が考えられますがIBから考えると楽しいことをしている時、その人は必ず意図のある行動つまり自発的行動を行っているはずです。行動ではないにしろ自発的に物事を考えたりしていると思います。逆につまらない時間はその人は自発的にほぼ何もしていないと思います。あれしろこれしろなど受動的になっていませんか?IBはそのような大きな時間のことではありませんが、数msの差が幾つも重なれば大きな体感時間の差になると思います。もし退屈な時間を短く済ませたいならば無理矢理にでも自発的行動をとってみようと僕は思いました。

 あまり続けても冗長な記事となってしまうためここで一回切ります。ここまで読んでいただいた方いらっしゃったらありがとうございました。

 次回は具体的にIBを使ってどんなことを実験するのかと実験方法まで書ければいいな。

 

次回↓↓

parco1021.hatenablog.com

 

 

参考図書 

 

もしよければ↓ぽちっと↓お願いします。

ブログランキング・にほんブログ村へにほんブログ村 PVアクセスランキング にほんブログ村

映画ワンピース スタンピードを公開初日に見てきた感想※ネタバレややあり

 

はじめに

このブログの対象は

・既に映画を観てこんな細かいことに気付いたぞって人

・煩雑な文章でも気にならない人←これ大事

つまり未視聴者などあらすじを確認したい人にとってはあんま…って感じになっちゃう

 

まずは予告↓↓

ゲrrrrrrrrrッロおもしろかった!!!!!!!

今まで二回観たい映画とかなかったんだけどこの映画はまた観たいと思った。てか観る。なんなら買う。小説も買う。文章で色々補填してあるだろうし絶対買う。

 

今回の映画のみどころ(若干ネタバレ?)

今回の見どころはやっぱりキャラの多さ。最悪の世代は全員出た。当然我らがウルージ様も極上のスマイルを見せてくださり、15億のルフィにも臆さず交戦するなど元気であられた。パンダマンが僕の体感だと10回ぐらい出てた気がする(実際はもっと多いかも)。まあパンダマンはどうでもいいんだけど。ナチュラルにケイミ―とパッパグとはっちゃん出てたしコニスもオープニングで背中だけ出てた気もする。あとはグラント(アニオリのキャラ)も1フレームぐらい出ててビビった 。他は映画常連となったルッチ君とサボ君。七武海もウィーブルとクマとドフィとジンベエ以外新旧揃って出たかな。個人的にジンベエいつ出るかなってわくわくしてたんだけど出なかったのは残念。多分時系列的にWCL編の後だから仕方ないのかも。エンディングではっちゃんと革命軍が手振るシーンあったけどこれコアラと再会してないのかな…。クロコさんとロビンの再開させるのもびっくりしたしこういうたくさんキャラ出す映画だと関係性とか考えなきゃいけないから大変そうだよね。

 

今回のラスボス・バレットについて

バレットは元ロジャー海賊団(他にも過去にあるけど)で、「"鬼"の跡目」とも呼ばれており、作中ではバギーに「レイリーに匹敵する」と言われています。実際に最悪の世代全員を相手に圧倒するなど正直「これどう倒すんだ…」って思ってた。ていうかバレットすげええともなったけど「これと同等のレイリーさん何者だよ…」の気持ちの方が大きかった。いや本当にどういうこと…??

 

ウソップさん

今回、真っ先にバレットにボコされちゃうウソップさん。この時バレットに言われた(ウソップは気絶してたから気付いてないかも)言葉が「弱い、使えない部下なんか切り捨てろ」でもうこれね…。W7でルフィに言ったセリフと重なっちゃってなんかつらくなっちゃったよ…。

おわりに

こんなに見づらく、ただ興奮冷めやらぬ中書いた雑な文章を読んでくださってありがとうございました。何か間違いやこんな発見したぞ!ってのがあったらコメントで教えていただけると幸いです!

グッズたくさんあったけどおっさん達が群がってて買えなかった…。パズルとか欲しかった。

[rakuten:cinemacollection:10277483:detail]

 

 

 

もしよければ↓ぽちっと↓お願いします。

ブログランキング・にほんブログ村へにほんブログ村 PVアクセスランキング にほんブログ村

Python3で大容量のcsvファイルを分割して読み込む

はじめに

この記事は記事タイトルの趣旨に関係のない所謂冗長なコードとなってしまっているので書き直しました。以下の記事へ飛んでいただけると幸いです。

parco1021.hatenablog.com

 

実験の講義で大容量のcsvファイルをなるべく高速に検索するシステムを作ることになり、Pythonを使うことにした。ちなみにPythonは動作がありえん遅いためこの課題には不適切だけどとにかくPythonが使いたかった。

 

使用機材

RaspberryPi

Python3.X

コード


import csv
import pandas as pd

df = pd.read_csv('True.csv',chunksize = 8000000,names=('id','time','lati','long','url','tag'),usecols=['time','lati','long','url','tag'])
for r in df:
    for row_index,row in r.iterrows():
        if row[4] == sys.argv[1]:
           for i in range(0,4):
              print(row[i])

コード自体は短い。Pythonで大容量ファイルを使うなんてことはそうそうないから他にも普通にopen csvして一行ずつ読み込んだり試したけどどうも動作が遅いしスマートなコードにならなかったからやめた。

 

コードの説明

今回はpandasライブラリを使った。大容量に強いらしいし。

まずpandasを使ってファイルを読み込む。この時、chunksizeでファイルを分割する。usecolsで使うカラムを指定。iterrows()を用いてリスト形式で出力。sys.argv[]はphpのexec()関数から渡された値(この場合だとユーザが打ち込んだ検索ワード)が検索対象のタグと一致した時に~って処理をしてる。一致したらそのデータ出力という処理が全体の概要。

緑字の説明

chunksizeは一回で何行データを読み込むかを指定する。例えば今回の実験では2000万行のcsvファイルを扱ったが、chunksizeを1000万と指定すれば1000万×2回に分割、400万と指定したら400万×5回に分割することができる。なぜそんなことをする必要があるのかというと、メモリにのらないほどの大容量ファイルだと一度に読み込もうとすると読み込むことができない。そこでファイルをメモリにのる程度に分割することで大容量ファイルでも読み込むことを可能とする。当然分割するファイルが多いほど(chunksizeが小さいほど)実行速度は遅くなってしまうため使用機材のメモリが許す限り大きな値に設定すべきである。今回使ったラズパイ君は1GBしかメモリがないからchunksizeもとても小さくなってしまい(100万ぐらい)、結局思ったより早くならなかった。もっとメモリが大きかったりファイルが小さかったりしたらいい感じになったかも。

もしよければ↓ぽちっと↓お願いします。

ブログランキング・にほんブログ村へにほんブログ村 PVアクセスランキング にほんブログ村

 

 

 

【Python3】「DeprecationWarning: Call to deprecated function ~」の解決方法

ある日

Pythonでエクセルのデータ解析するかぁ~と思ってファイルを開こうとしたら…

DeprecationWarning: Call to deprecated function get_sheet_names (Use wb.sheetnames).

 のエラー文。最初は???って感じだったけど英単語調べた結果意訳すると「おめえそろそろなくなるメソッドつかってんぞ」とのこと。そして親切にも(Use ~)と教えてくれているので素直に従うと解決した。

 まとめるほどのことでもないけどエラー文を読まず時間を浪費した自分への戒めとして残す。

 

おわり

もしよければ↓ぽちっと↓お願いします。

ブログランキング・にほんブログ村へにほんブログ村 PVアクセスランキング にほんブログ村

二次方程式の解の公式の導出方法をざっくり

はじめに

 二次方程式の解の公式は誰でも知っている公式だと思います。しかし導出できますか?と聞かれるとできない人も一定数いると思います。というか導出できる云々より中学生の時に機械的に覚えさせられたから導出するという発想にすら至らないかもしれません。高校数学までならばほぼすべての公式が導出可能です。数Ⅲなどでは一部大学数学でしか証明できないものもありますが。大学の理論数学とかはもう導出とかそういう次元じゃないので高校数学がどれだけ良心的だったかわかります。

本題

まずは二次方程式の解の公式

 0=ax^2+bx+c x=\frac{-b±\sqrt{b^2-4ac}}{2a}

見慣れたものだと思います。大学生になるとこの式は忘れているかもしれません。僕もうろ覚えでした。これを導出します。導出方法は平方完成をすればいいだけなのでそんな難しくありません。

 まず、前提条件として二次方程式であるためa≠0、bとcは任意の実数です。
 
 0=ax^2+bx+c =a(x^2+\frac{bx}{a})+c
 0=a((x+\frac{b}{2a})^2-\frac{b^2}{4a^2})+c
 (x+\frac{b}{2a})^2=\frac{b^2}{4a^2}-\frac{4ac}{4a^2}
 (x+\frac{b}{2a})=\frac{±\sqrt{b^2-4ac}}{2a}
 x=\frac{-b±\sqrt{b^2-4ac}}{2a}
もっと詳細に書く気満々だったけど思ったより数式を打つのがダルかったので色々省略。質問、訂正あったら教えてください。頭やわらかくするつもりで書き始めたけど結
Texの勉強になってしまって頭の頭痛が痛い。
おわり。
 

 

もしよければ↓ぽちっと↓お願いします。

ブログランキング・にほんブログ村へにほんブログ村 PVアクセスランキング にほんブログ村

【Python3】改行しながらテキストファイルに出力する

敗北者

改行できないの悔しすぎる。俺は敗北者。

コード1


#coding:utf-8
import random

number = [0.1,0.2,0.3,0.4,0.5,0.7,0.9]
delay = random.choice(number)

_delay = str(delay)

f = open('a.txt','a')
f.write('\n'.join(_delay))
f.close

出力

0

.

3

0

.

4など

…そうじゃないんだけどなあ

原因

原因として考えられるのは「0.3」を書き込んでいるんじゃなくて「0」「.」「3」を書き込んでるからそのたびに改行コードを打ち込んじゃっている。そこを力業でデバックする。

コード2


#coding:utf-8
import random

number = [0.1,0.2,0.3,0.4,0.5,0.7,0.9]
delay = random.choice(number)

_delay = str(delay)

f = open('a.txt','a')
f.write(_delay)
f.write('\n')
f.close

これはf.write()で書き込んだ後に改行コードを打ち込んでいるから確実っちゃあ確実だけどスマートじゃないからあんまやりたくなかった。。。

出力

0.3

0.4

ちゃんと思った通りに動いた。

余談

「かいぎょう」って打って一番に「開業」出てくるのやめてほしい。開業コードとかないから。

もしよければ↓ぽちっと↓お願いします。

ブログランキング・にほんブログ村へにほんブログ村 PVアクセスランキング にほんブログ村

Psychopy(Python)とArduinoでシリアル通信してみた

 

目的

python3からArduinoへシリアル通信を行い、ある文字列がきたらモーターを振動させるという処理をすること

プログラム(失敗例)

Python

import serial 
import time 
print('Start') 
ser=serial.Serial('COM5',9600) 
ser.write("a") 
print('Send')
if ser.in_waiting>0:
 line = ser.read() 
 print(line) 
ser.close()

 

Arduino

void setup() {
  Serial.begin(19200);
  pinMode(8, OUTPUT);  
}

void loop() {
  byte VibON;
  VibON = Serial.read();
 switch(VibON){
  case 'a':
    digitalWrite(8, HIGH);
    delay(40);
    digitalWrite(8, LOW);
    delay(20);
    break;
  default:
  break;
 }
  delay(1);
}

プログラムの説明

 上記のプログラムは正しく動作しないが、一応解説をする。まず、python側でシリアル通信をするためのserialをインポートする。これはデフォルトで入っていたり入っていなかったりするのでない場合は(py -m)pip install pyserialをcmd上で入力すれば入れられる。py -mはWindowsの場合にのみ必要。まずWindowsの不便さでここがうまくいかくて苦労したけどそれは省略。最初からlinux使えばよかた。serial.Serial()の引数は各々帰る。そしてwrite()でArduino側へ送信する。また、Arduinoから返ってきた値を表示するためにread()も書いてある。

 Arduino側はいたってシンプルにSerial.read()で読み取ったデータがaならばモーターを振動させるという処理をさせている。しかしこのプログラムで実行しようとするとエラーが出る。

原因解明

 Arduino側は普通にコンパイルできるしシリアルポートでaを送ると振動する。python側のエラー文を見ると「byte型で送れや」と怒られている。調べてみるとserialはbyte型しか送れないっぽい。じゃあaをbyte型にするにはb'a'とするだけでいいから直して実行するとエラーは出ないがモーターが動かない。


ser.write("a") → ser.write(b"a")

 

Arduinoから返っても来ない。わけがわからないのでとりあえず送るものを表示させてみたらb'a'と送っている。byte型で送っているから当たり前なんだけどこれじゃあaではないのでArduino側も振動するはずがない。次になぜArduinoから返ってこないか考える。通信したことを示すランプは光るし大した処理はしていないからよくわからん。とりあえずネットで検索をかけまくる。そしたらポートを開いてから書き込む間に遅延を発生している人がちらほら(全員じゃない)。とりあえず適当に遅延をかけてみたらArduinoから値が返ってきた!!多分処理が追い付かないまま書き込もうとしちゃって結局書き込めてない的な感じかな。


ser=serial.Serial('COM5',9600) 
ser.write("a") 
↓
import time

ser=serial.Serial('COM5',9600) 
time.sleep(2)
ser.write(b"a") 

 いい感じになってきたのであとはモーターぶるっとさせるだけ。単純に文字列比較だと一生aは送られないからそこを考える。考えた過程とか忘れたので結論char型にして先頭からaを探すという処理をすることで解決した。このプログラム自体は簡単だった。成功プログラムを以下に示す。

プログラム(成功)

Python

import serial
import time

print('Start')
ser=serial.Serial('COM5',9600)
time.sleep(2)
ser.write(b"a")
print('Send')
#time.sleep()
if ser.in_waiting>0:
    
 line = ser.read()
 print(line)
ser.close()
Arduino
void setup() {
  Serial.begin(9600);
  pinMode(8, OUTPUT);  
}

void loop() {
  if(Serial.available() >0){
  int Vib=Serial.available();
  char VibON[Vib+1];
  
  for(int i=0; i<Vib; i++){
    VibON[i] = Serial.read();
    if(VibON[i] == 'a'){
      Serial.print(VibON);
    digitalWrite(8, HIGH);
    delay(1000);
    digitalWrite(8, LOW);
    delay(20);
    }
    VibON[Vib]= '\0';
    Serial.print(VibON);
  }
 }
  delay(1);
}

 

今回使ったArduinoは以下。非純正買ってもいいけど変なところで苦労するかも。

おわり。

 

 

 

もしよければ↓ぽちっと↓お願いします。

ブログランキング・にほんブログ村へにほんブログ村 PVアクセスランキング にほんブログ村

【Python】'range' object does not support item assignment の解決方法

結論:pythonによるバージョンの違いから吐かれるエラー

このエラー文自体の意味はこれは今のバージョンじゃ使えないよ~ってこと。Python2だとそのままa=range(M)みたいに使えたんだけどPython3からは使えなくなった。

 

どうすれば解決?

range()を使って乱数生成するのは同じ。ただ関数list()を使って

a = list(range(M)) とするとエラーが消えて正しく表示された。注意として変数(この場合はa)を関数名(list)と同じにする、つまり

list = list(range(M))のようにすると変数名と関数名を同じにするな!とエラー文が帰って来るので注意

 

参考文献

blog.tstylestudio.com

 

もしよければ↓ぽちっと↓お願いします。

ブログランキング・にほんブログ村へにほんブログ村 PVアクセスランキング にほんブログ村

自己紹介

大まかな自己紹介

 2019年現在、情報学系統を専攻している大学生(B3)です。誰かの言葉ではなく自分の言葉でどこかでアウトプットできないだろうかと思いこのようなブログをはじめてみようかなと思いました。また、学業だけでなく日常的なことも書いていこうと思っています。アウトプットとしてこのブログを書くつもりでいるため多少読みにくいことや誤ったことがあるかもしれませんがご了承願います。また、言葉遣いなども不安定だと思います。

 少し触ったことがあるものはLaravelとPythonです。機械学習やWebシステムに興味があります。

 基本的には日記のようなものです。コメント、アドバイスなどどしどし待ってます!

 

 

もしよければ↓ぽちっと↓お願いします。

ブログランキング・にほんブログ村へにほんブログ村 PVアクセスランキング にほんブログ村

スポンサーリンク