kaeken(嘉永島健司)のTech探究ブログ

主に情報科学/情報技術全般に関する知見をポストします。(最近は、特にData Science、機械学習、深層学習、統計学、Python、数学、ビッグデータ)

Python/scikit-learn/分類精度の評価指標について

f:id:kaeken:20180203200300p:plain


前回は、機械学習のクラス分類精度を評価するために、まず混同行列 (Confusion matrix)についてまとめました。

Python/scikit-learn/分類精度を評価する際に使われる混同行列 (Confusion matrix)について - データサイエンティストへの修行日記

今回は、混同行列の値TP,FP,FN,TNを使った指標についてまとめていきたいと思います。

あらためて、混同行列のテーブルを見ていきます。

f:id:kaeken:20180202131648p:plain

前回、以下のようにパターンが存在することを示しました。

パターン1:正答と予測して、実際正答だった場合
パターン2:正答と予測して、実際誤答だった場合
パターン3:誤答と予測して、実際正答だった場合
パターン4:誤答と予測して、実際誤答だった場合

混同行列(Confusion matrix)では、それぞれのパターンを、以下のように表現しています。

パターン1:真陽性: TP (True-Positive)
パターン2:偽陽性: FP (False-Positive)
パターン3:偽陰性: FN (False-Negative)
パターン4:真陰性: TN (True-Negative)

それぞれの頭文字の意味は、以下の通りです。

T(True, 真):予測と実際が一致している状態
F(False, 偽):予測と実際が一致していない状態
P(Positive, 陽):正答が予測された状態
N(Negative, 陰):誤答が予測された状態

これらのパターンを用いて、精度を評価するための指標があります。

Confusion matrix - Wikipedia

今回は、主に4つの以下をとりあげます。

  • 正解率 (Accuracy)
  • 適合率 (Precision) ※精度とも言う
  • 検出率 (Recall)
  • F値 (f-score)

それぞれの指標の定義は、以下の通りです。

正解率 (Accuracy) = TP+TN / 全体

→全体のうち、予測通り正誤分類できた割合

真陽性: TP (True-Positive)
真陰性: TN (True-Negative)


適合率 (Precision) = TP / (TP + FP)

→予測が正答だった中で、予測通り正答分類できた割合

真陽性: TP (True-Positive)
偽陽性: FP (False-Positive)


検出率 (Recall) = TP / (TP + FN)

→実際に正答だった中で、予測も正答だった割合

真陽性: TP (True-Positive)
偽陰性: FN (False-Negative)


F値 (f-score) = 適合率と検出率の調和平均

→ 適合率と検出率の調和平均を求めて、極端に振れないようにする値です。
F1 score - Wikipedia


以上が主な分類精度の評価指標となります。

それぞれの実装は、scikit-learnでメソッドになっていますので、以下で実装例が確認できます。

  • 正解率 (Accuracy) : sklearn.metrics.accuracy_score
  • 適合率 (Precision) : sklearn.metrics.precision_score
  • 検出率 (Recall) : sklearn.metrics.recall_score
  • F値 (f-score) : sklearn.metrics.f1_score

API Reference — scikit-learn 0.19.1 documentation

Classification metrics


また、上記のうち、適合率・検出率・F値をまとめて表示する
sklearn.metrics.classification_report
が定義されていますので、便利です。

#sklearn.metrics.classification_report
from sklearn.metrics import classification_report
y_true = [0, 1, 2, 2, 2]
y_pred = [0, 0, 2, 2, 1]
target_names = ['class 0', 'class 1', 'class 2']
print(classification_report(y_true, y_pred, target_names=target_names))
実行結果
             precision    recall  f1-score   support

    class 0       0.50      1.00      0.67         1
    class 1       0.00      0.00      0.00         1
    class 2       1.00      0.67      0.80         3

avg / total       0.70      0.60      0.61         5

以上で、主な分類精度の評価指標についてまとめました。

機械学習では、必ず精度を評価しながら、過学習に陥らず、精度を上げていくことが重要になります。

(2018-02-03)気になるML/DL/DSネタ:教えない先生、Custom Vision Service、『仕事ではじめる機械学習』著者座談会

未来を変える技術20 - AI活用で「教えない先生」が登場、1800億円に膨らむ教育×IT市場:ITpro

同社は2014年から東京大学の松尾豊特任准教授と共同で、生徒が動画のどこで躓いたかやコンテンツ間の関連性を分析。先に何を学べば躓かないのかや何を復習すれば知識が定着するのかといった学び方が分かってきた。これにより百人百様の学習プログラムが提供できるようになった。


MicrosoftのAIをカスタマイズしてハンバーガーとチーズバーガーを区別させよう:特集:AIをアプリに組み込もう - @IT

Microsoftが提供するCustom Vision Serviceを取り上げる。これは幾つかの画像をアップロードして、学習させることで、Microsoftが提供している画像認識技術をプログラマーが独自にカスタマイズできるというサービスだ。


【AI people:vol.7】『仕事ではじめる機械学習』著者座談会:前編 きっかけは「没原稿の供養プロジェクト」だった | blog - 人工知能(AI)/機械学習に特化した勉強会コミュニティ【Team AI】

今回インタビューに参加してくださったのは、有賀康顕(ありが・みちあき)氏(@chezou)と中山心太(なかやま・しんた)氏(@tokoroten)。1時間以上に渡り、出版裏話からエンジニアへのアドバイスまで広く伺いました。


国立がん研究センター公表の「がん5年生存率データ」から年齢・進行度などの影響を取り除いたリアルなデータを作成した強者が現れる - GIGAZINE

統計モデリングを用いて各因子の影響度を排除した状態での5年後生存率を調べて病院の善し悪しを論じようというのがStatModelingさんの狙いです。なお、StatModelingさんの出した結果も仮定に基づく推定結果であり、真実と断定しているわけではない点には注意が必要です。


(PDF)人工知能とデータサイエンティストの役回り

樋口知之 (情報・システム研究機構 統計数理研究所


Python/scikit-learn/分類精度を評価する際に使われる混同行列 (Confusion matrix)について

f:id:kaeken:20180202131648p:plain

機械学習のクラス分類精度を評価するために、混同行列 (Confusion matrix)が用いられます。

Confusion matrix - Wikipedia

In the field of machine learning and specifically the problem of statistical classification, a confusion matrix, also known as an error matrix,[4] is a specific table layout that allows visualization of the performance of an algorithm, typically a supervised learning one (in unsupervised learning it is usually called a matching matrix).


何かを予測した場合の精度を評価するには、予測した結果と、実際の結果と比較します。

また、結果には、正しい結果と誤った結果があります。

混同行列 (Confusion matrix)では、2つの軸を設定します。

予実の軸:予測 or 実際
正誤の軸:正答 or 誤答

予実と正誤それぞれの状態をかけ合わせると、以下の4通りになります。

パターン1:正答と予測して、実際正答だった場合
パターン2:正答と予測して、実際誤答だった場合
パターン3:誤答と予測して、実際正答だった場合
パターン4:誤答と予測して、実際誤答だった場合

混同行列(Confusion matrix)では、それぞれのパターンを、以下のように表現しています。

パターン1:真陽性: TP (True-Positive)
パターン2:偽陽性: FP (False-Positive)
パターン3:偽陰性: FN (False-Negative)
パターン4:真陰性: TN (True-Negative)

それぞれの頭文字の意味は、以下の通りです。

T(True, 真):予測と実際が一致している状態
F(False, 偽):予測と実際が一致していない状態
P(Positive, 陽):正答が予測された状態
N(Negative, 陰):誤答が予測された状態

TP,FP,FN,TNそれぞれのパターンを表にすれば、以下のようになります。

f:id:kaeken:20180202131648p:plain

縦軸:予測、横軸:実際

では、scikit-learnで混同行列 (Confusion matrix)を使ってみますと、以下のようなコマンドになります。

from sklearn.metrics import confusion_matrix
pred_result = [1, 1, 1, 0]#予測の結果
true_result = [0, 1, 0, 1]#実際の結果
#予実とも1は、1個なのでTP:1
#予測1で実際0なのは、2個なのでFP:2
#予測0で実際1なのは、1個なのでFN:1
#予実とも0は、0個なのでTN:0

tn, fp, fn, tp = confusion_matrix(true_result, pred_result).ravel()#混同行列で解きほぐした結果を取得
(tp, fp, fn, tn)#正正,正誤,誤正,誤誤に順番を整理して表示
実行結果
(1, 2, 1, 0)

他のパラメータは以下に詳述されています。

sklearn.metrics.confusion_matrix — scikit-learn 0.19.1 documentation

sklearn.metrics.confusion_matrix(y_true, y_pred, labels=None, sample_weight=None)


なお、

上記は、正答/誤答といった二値分類でしたが、多値分類でも可能です。

また、縦軸:予測、横軸:実際を逆にして、縦軸:実際、横軸:予測にする表現方法もあります。

それでは、

この混同行列の値TP,FP,FN,TNを使った指標については、後日まとめていきたいと思います。

(2018-02-02)気になるAI/ML/DSニュース・記事・サービスなど

米国500社の財務諸表ビッグデータ分析で見えた7つの事実 - データで見る世界

バイアスを取り除く方法はただ一つ。データ分析です。データは嘘をつきません。賢そうな人の意見を鵜呑みにするのではなく、自分で生のデータを分析すれば、事実にたどり着けます。


OpenML Guide

OpenML aims to make machine learning and data analysis simple, accessible, collaborative and open, automating many manual tasks to create a frictionless working and learning environment.


テキスト解析:自然言語理解 - Yahoo!デベロッパーネットワーク

自然言語理解Web APIを利用してアプリケーションを開発 Yahoo!音声アシストでも使われている自然言語理解Web APIを利用して、アプリケーションを作成できます。


アマゾンの「レジなしコンビニ」で見えた究極のデータビジネス

「アマゾンは市場を独占することよりも、データを得ることのほうが価値を持つと知っているからだ。膨大な顧客の購買データがあれば、様々な商品のレコメンドに活用可能だ。」


"All models are wrong; but some are useful"(全てのモデルは間違っている、だが中には役立つものもある)という格言 - 六本木で働くデータサイエンティストのブログ

統計学機械学習の世界ではよく引用される"All models are wrong; but some are useful"(全てのモデルは間違っている、だが中には役立つものもある)という格言ですが、2013年に亡くなった統計学の大家George E. P. Boxの言葉だと伝わっています」


世界最大の「アルゴリズム市場」を作ったエンジニア2名の奮闘 | Forbes JAPAN(フォーブス ジャパン)

「6万を超える開発者が利用する世界最大のアルゴリズムマーケットプレイス「Algorithmia(アルゴリズミア)」は、コミュニティが作成した機械学習モデルを使ってアプリケーションの開発を容易にするサービスを提供している。現在、4500以上のアルゴリズムが登録されているが、その多くは機械学習関連だ。」


静かに広がる「アンチ深層学習」「アンチAI」 - 日経トレンディネット

AIという言葉が、意味が不明瞭のまま使われる「バズワード」と化し、猫も杓子もなんにでも使われていることへの反感ではなかろうかと思う


【実録PoC】毎月数百件以上の文書スキャン業務はロボットで置き換え可能なのか:RPA導入ガイド(5) - @IT

今回は、RPAの基本となる、RDA(Robotic Desktop Automation)のPoCについて共有します。覚えていただきたいキーワードは人手からロボットへの「置き換え」です。「ロボットで置き換え可能かどうか」がPoCの第一目的となるからです。


Python/pandas公式チートシート解説:前処理のゴールとなるTidy Dataとは

f:id:kaeken:20180202085619p:plain

pandas githubのドキュメントに公式のチートシートがアップされています。 github.com

このpandasチートシートには、重要な概念やコマンド実行方法が整理されていますので、項目をひとつずつ解説していきます。

なお、このチートシートは、もともとR言語チートシートにインスパイアされたものらしいです。

今回は、pandasですが、今後、R言語でも同様に解説していく予定です。

それでは、まずはじめに、Tidy Dataについて整理します。

Tidy Dataとは

Wikipediaでは以下のように解説されています。

Tidy data - Wikipedia

Tidy data is the data obtained as a result of a process called data tidying. It is one of the important cleaning processes during big data processing and is a recognized step in the practice of data science. The tidy data sets have structure and working with them are easy, they’re easy to manipulate, model and visualize. Tidy data sets main concept is to arrange data in a way that each variable is a column and each observation (or case) is a row.


日本語訳では「整然データ」と呼ばれ、以下の4つの特徴を持ちます。

整然データとは何か|Colorless Green Ideas

整然データとは、1) 個々の変数が1つの列をなす、2) 個々の観測が1つの行をなす、3) 個々の観測の構成単位の類型が1つの表をなす、4) 個々の値が1つのセルをなす、という4つの条件を満たした表型のデータのことであり、構造と意味が合致するという特徴を持つ。R言語などを用いたデータ分析の際には非常に有用な概念である。


Tidy Dataの概念は、リレーショナルデータベースの正規化と類似しているので、すんなり理解できました。

一方、以下のように、上記の特徴に反するデータは、整然データTidy Dataではなく、雑然データ(messy data)と呼ばれます。

  • 個々の変数 (variable) が1つの列 (column) をなす
    →1つの変数(種類)が複数の列に分かれていたり、複数の変数(種類)が1つの列に入っていれば、整然データTidy Dataではない。

  • 個々の観測 (observation) が1つの行 (row) をなす
    →1つのデータが複数の行/レコードに分かれたり、複数のデータが1つの行/レコードに入っていれば、整然データTidy Dataではない。

  • 個々の観測の構成単位の類型 (type of observational unit) が1つの表 (table) をなす
    →ひとつの種類のデータセットが複数のテーブルに分かれていたり、複数の種類のデータセットがひとつのテーブルに入っていれば、整然データTidy Dataではない。

  • 個々の値 (value) が1つのセル (cell) をなす
    →ひとつの値が複数のセルに分かれていたり、複数の値が一つのセルに入っていれば、整然データTidy Dataではない。

人間にとってわかりやすい表だとしても、データ分析する場合は、上記のようなTidy Dataに変換する必要があります。

現場では、人間が見て分かりやすい表にされたデータを使って機械学習させることが多いので、整然データTidy Dataへの変換は、必須と言えます。

次回から、Tidy Dataにするための道具であるpandasのチートシート解説をしていきます。

目次

  • Tidy Data (いまここ)
  • Syntax
  • Reshaping Data
  • Subset Observations(Rows)
  • Subset Variables(Columns)
  • Summarize Data
  • Group Data
  • Handling Missing Data
  • Make New Columns
  • Combine Data Sets
  • Windows
  • Plotting

Python/pandas エンコードされたone-hotデータをデコードする方法

f:id:kaeken:20180201203956p:plain

機械学習の学習用データでよく使われるone-hotエンコーディングされたデータがあります。

f:id:kaeken:20180201202817p:plain

one-hotエンコーディング処理は、さまざまなライブラリで実装されています。

sklearn.preprocessing.OneHotEncoder — scikit-learn 0.19.1 documentation http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html

ただ、one-hotデコーディング、 つまり、もとのデータに戻す処理が見つかりませんでした。

f:id:kaeken:20180201202951p:plain

そこで、 以下のようにpandasのデータフレームを使って、one-hotデコーディングする処理を作成してみました。

def onehot_decoder(df):
    colname_list = []
    for index, row in df.iterrows():#各行を取得
        for k,v in enumerate(row):#各列の値を取得
            if int(v) == 1:#ワンホットになっている列のカラム名を取得
                colname_list.append(df.columns[k])
                break

    #デコード済みリストを新規列として追加
    df_add = pd.DataFrame(colname_list,columns=['decoded'])
    return df_add

res = onehot_decoder(df_sample)

もう少し簡潔に書けるとは思いますが、わかりやすさのため、このままにしておきます。

前処理方法は、データによって多数のパターンがあり、 scikit-learnのpreprocessingモジュールでさまざまなものが作られています。

API Reference — scikit-learn 0.19.1 documentation http://scikit-learn.org/stable/modules/classes.html#module-sklearn.preprocessing

preprocessing.Binarizer([threshold, copy])   Binarize data (set feature values to 0 or 1) according to a threshold
preprocessing.FunctionTransformer([func, …])  Constructs a transformer from an arbitrary callable.
preprocessing.Imputer([missing_values, …])    Imputation transformer for completing missing values.
preprocessing.KernelCenterer    Center a kernel matrix
preprocessing.LabelBinarizer([neg_label, …])  Binarize labels in a one-vs-all fashion
preprocessing.LabelEncoder  Encode labels with value between 0 and n_classes-1.
preprocessing.MultiLabelBinarizer([classes, …])   Transform between iterable of iterables and a multilabel format
preprocessing.MaxAbsScaler([copy])  Scale each feature by its maximum absolute value.
preprocessing.MinMaxScaler([feature_range, copy])   Transforms features by scaling each feature to a given range.
preprocessing.Normalizer([norm, copy])  Normalize samples individually to unit norm.
preprocessing.OneHotEncoder([n_values, …])    Encode categorical integer features using a one-hot aka one-of-K scheme.
preprocessing.PolynomialFeatures([degree, …]) Generate polynomial and interaction features.
preprocessing.QuantileTransformer([…])    Transform features using quantiles information.
preprocessing.RobustScaler([with_centering, …])   Scale features using statistics that are robust to outliers.
preprocessing.StandardScaler([copy, …])   Standardize features by removing the mean and scaling to unit variance
preprocessing.add_dummy_feature(X[, value]) Augment dataset with an additional dummy feature.
preprocessing.binarize(X[, threshold, copy])    Boolean thresholding of array-like or scipy.sparse matrix
preprocessing.label_binarize(y, classes[, …]) Binarize labels in a one-vs-all fashion
preprocessing.maxabs_scale(X[, axis, copy]) Scale each feature to the [-1, 1] range without breaking the sparsity.
preprocessing.minmax_scale(X[, …])    Transforms features by scaling each feature to a given range.
preprocessing.normalize(X[, norm, axis, …])   Scale input vectors individually to unit norm (vector length).
preprocessing.quantile_transform(X[, axis, …])    Transform features using quantiles information.
preprocessing.robust_scale(X[, axis, …])  Standardize a dataset along any axis
preprocessing.scale(X[, axis, with_mean, …])  Standardize a dataset along any axis

上記も後日紹介していきます。

気になったAI/ML/DSニュース・サービスなど(2018-02-01)

Googleオープンソース機械学習ライブラリの最新版「TensorFlow 1.5」を発表:使い勝手やモバイル対応、GPUサポートが向上 - @IT http://www.atmarkit.co.jp/ait/articles/1801/30/news038.html


24研究室と1日で会える!人工知能・IoT・ビッグデータ分野での産学連携マッチングフェア | 人工知能ニュースメディア AINOW http://ainow.ai/2018/01/31/132591/


イー・ガーディアンが動画音声のテキスト化によるキーワード検知「TextVoice」展開 | Web担当者Forum https://webtan.impress.co.jp/n/2018/01/31/28178


東京大学の松尾研究室が無料公開している「Deep Learning基礎講座演習コンテンツ」の自主学習方法 - karaage. [からあげ] http://karaage.hatenadiary.jp/entry/2018/01/31/073000


AIの権威ヌグ氏、AI開発ファンド設立 ソフトバンクなど支援  :日本経済新聞 https://www.nikkei.com/article/DGXMZO26353570R30C18A1000000/


Memory AI – Fully Automatic Time Tracking Powered by Deep Learning - Timely https://timelyapp.com/memory-ai?ref=producthunt


スタンフォード大学が患者の余命を予測する人工知能システムを開発 | ワールド | 最新記事 | ニューズウィーク日本版 オフィシャルサイト https://www.newsweekjapan.jp/stories/world/2018/01/post-9418.php

Python/pandasでグルーピングした複数行をカンマ区切りの一行にする方法

f:id:kaeken:20180131225205p:plain

Python/pandasを使って、以下のようにグルーピングした複数行を一行にする方法について解説します。

before

 col1  col2
0     1  hoge
1     2  fuga
2     3  piyo
3     1   foo
4     2   bar
5     3   baz
after:col1でグルーピングした上で、col2を一行に集約

col1
1    hoge,foo
2    fuga,bar
3    piyo,baz

まず、以下のようなデータフレームを準備します。

import pandas as pd

df = pd.DataFrame(
    {"col1":[1,2,3,1,2,3], "col2":["hoge","fuga","piyo","foo","bar","baz"]},
    )
print(df)

次に、データフレームをgroupbyでグルーピングします。

そして、apply()で自作関数を実行しますが、その際に、無名関数lambdaを使えば、各行に対して同じ処理を適用します。

自作処理は、指定文字で結合するjoin()を使って、カンマ区切りにしています。

df = df.groupby('col1').col2.apply(lambda s : ','.join(s))
print(df)

lambda無名関数は、非常に便利で記述がすっきりしますので、おすすめです。

以上です。参考まで。


pandas.DataFrame.groupby — pandas 0.22.0 documentation https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.groupby.html


pandas.DataFrame.apply — pandas 0.22.0 documentation https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.apply.html


『ゼロから作るDeep Learning』数学用語一覧

f:id:kaeken:20171208014108p:plain

『ゼロから作るDeep Learning』に出てくる数学用語について調べていく。

ただ、定義だけ追っていても意味が分からないので、

実際の使われ方については、高校レベルの数学を別途復習が必要。

では、以下数学用語を列挙していく。

線形とは

https://ja.wikipedia.org/wiki/%E7%B7%9A%E5%9E%8B%E6%80%A7

線型性(せんけいせい、英語: linearity)あるいは線型、線形、線状、リニア(せんけい、英語: linear、ラテン語: linearis)とは、直線そのもの、または直線のようにまっすぐな図形やそれに似た性質をもつ対象および、そのような性質を保つ変換などを指して用いられている術語である[1]。対義語は非線型性(英語:Non-Linearity)である。

シグモイド関数について。 シグモイド関数 - Wikipedia

シグモイド関数(シグモイドかんすう、英: sigmoid function)は、 f:id:kaeken:20171208192612p:plain で表される実関数である。

なお、a をゲイン (gain) と呼ぶ。

狭義には、

ゲインが1の標準シグモイド関数 (英: standard sigmoid function) f:id:kaeken:20171208192739p:plain をさす。

実関数とは 関数 (数学) - Wikipedia

定義域も終域も実数の集合であるような関数を実関数 (real function) という

シグモイド関数内に出てくるネイピア数について

https://ja.wikipedia.org/wiki/%E3%83%8D%E3%82%A4%E3%83%94%E3%82%A2%E6%95%B0

ネイピア数(ネイピアすう、英: Napier's constant)は数学定数の一つであり、自然対数の底である。 記号として通常は e が用いられる。その値は e = 2.71828 … と続く超越数である

数学定数とは

https://ja.wikipedia.org/wiki/%E6%95%B0%E5%AD%A6%E5%AE%9A%E6%95%B0

数学定数(すうがくていすう)とは、なんらかの"面白い"性質を持った定数である。

自然対数とは

https://ja.wikipedia.org/wiki/%E8%87%AA%E7%84%B6%E5%AF%BE%E6%95%B0

自然対数(しぜんたいすう、natural logarithm)は、ネイピア数を底とする対数 (logarithm) である。

対数とは

https://ja.wikipedia.org/wiki/%E5%AF%BE%E6%95%B0

対数(たいすう、英: logarithm)とは、ある数 x を数 b の冪乗 bp として表わした場合の冪指数 p である。

超越数とは

https://ja.wikipedia.org/wiki/%E8%B6%85%E8%B6%8A%E6%95%B0

超越数(ちょうえつすう、英: transcendental number)とは、代数的数でない数、すなわちどんな有理係数の代数方程式 f:id:kaeken:20171208193644p:plain の解(英語版)にもならないような複素数のことである。

『Pythonからはじめる数学入門』7章(後半) 初等解析問題を解く / 高階微分および積分

f:id:kaeken:20171206212414p:plain

Pythonからはじめる数学入門』7章(後半) 初等解析問題を解く

の解説です。

7.5 高階微分と極大極小の計算

Derivativeクラスを使った微分オブジェクトのデフォルトは、 1階微分です。

高階微分をおこなうには、階数を第三引数に渡します。

ここでは、関数の1階微分と2階微分を使ってある区間の極大・極小を求める方法を示します。

定義域[-5,5]の関数 { \displaystyle
x^{5} - 30 x^{3} + 50 x
} を考えます。 f:id:kaeken:20171206212414p:plain

関数の極大値・極小値・最大値・最小値を求めるには、以下のように処理します。

#7.5 高階微分と極大極小の計算
from sympy import Symbol, solve, Derivative
x = Symbol('x')
f = x**5 - 30*x**3 + 50*x
d1 = Derivative(f, x).doit() #1階微分 階数を引数に指定するが、1階のときは省略
print('1階微分: {0}'.format(d1))
critical_points = solve(d1) #関数の臨界点
print('critical_points: {0}'.format(critical_points))
A = critical_points[2]
B = critical_points[0]
C = critical_points[1]
D = critical_points[3]

d2 = Derivative(f, x, 2).doit() #2階微分 階数を引数に指定
print('2階微分: {0}'.format(d2))

#2階微分の値が負なら極大点、正なら極小点、0なら未決
print('B: {0}'.format(d2.subs({x:B}).evalf()) )
print('C: {0}'.format(d2.subs({x:C}).evalf()) )
print('A: {0}'.format(d2.subs({x:A}).evalf()) )
print('D: {0}'.format(d2.subs({x:D}).evalf()) )
#AとCは負なので極大点、BとDは正なので極小点

x_min = -5 #端点最小値
x_max = 5 #端点最大値
print('x_min: {0}'.format(f.subs({x:x_min}).evalf()) )
print('x_max: {0}'.format(f.subs({x:x_max}).evalf()) )
#最大値を求めるためには、端点とA,Cで比較
print('A: {0}'.format(f.subs({x:A}).evalf()) )
print('C: {0}'.format(f.subs({x:C}).evalf()) )
#点Aが最大値

#最小値を求めるためには、端点とB,Dで比較
print('B: {0}'.format(f.subs({x:B}).evalf()) )
print('D: {0}'.format(f.subs({x:D}).evalf()) )
#点Dが最小値

結果

1階微分: 5*x**4 - 90*x**2 + 50
critical_points: [-sqrt(-sqrt(71) + 9), sqrt(-sqrt(71) + 9), -sqrt(sqrt(71) + 9), sqrt(sqrt(71) + 9)]
2階微分: 20*x*(x**2 - 9)
B: 127.661060789073
C: -127.661060789073
A: -703.493179468151
D: 703.493179468151
x_min: 375.000000000000
x_max: -375.000000000000
A: 705.959460380365
C: 25.0846626340294
B: -25.0846626340294
D: -705.959460380365

7.6 勾配上昇法を用いて最大値を求める

7.6.1 勾配上昇法のジェネリックなプログラム

7.6.2 初期値について一言

.6.3 ステップサイズとイプシロンの役割

7.7 関数の積分を求める

#7.7 関数の積分を求める

#Integralオブジェクトで不定積分、定積分を扱う
from sympy import Integral, Symbol
x = Symbol('x')
k = Symbol('k')
i1 = Integral(k*x, x).doit() #関数k*xと積分する変数xでIntegralオブジェクトを作り積分を評価
print('関数kxの不定積分: {0}'.format(i1))

i2 = Integral(k*x, (x,0,2)).doit() #定積分は、変数x、下限0、上限2、といったセットをタプルで渡す
print('関数kxの定積分(xが0から2をとる場合): {0}'.format(i2))

結果

関数kxの不定積分: k*x**2/2
関数kxの定積分(xが0から2をとる場合): 2*k

7.8 確率密度関数

『Pythonからはじめる数学入門』7章(前半) 初等解析問題を解く

f:id:kaeken:20171205234404p:plain

Pythonからはじめる数学入門』7章(前半) 初等解析問題を解く

に関する解説です。

7.1 関数とは何か

7.1.1 関数の定義域と値域

数学そのものの説明は省略しますが、用語を記しておきます。

写像mapping
定義域domain
値域range

7.1.2 よく使われる数学関数

sin()などよく使われる数学関数の書き方です。

#7.1.2 よく使われる数学関数

import math
print(math.sin(math.pi/2))

import sympy
print(sympy.sin(math.pi/2))

from sympy import Symbol
theta = Symbol('theta')
sympy.sin(theta) + sympy.sin(theta)

結果

1.0
1.00000000000000
2*sin(theta)

7.2 SymPyでの仮定

変数の正負など仮定を指定する場合です。

#7.2 SymPyでの仮定assumption
from sympy import Symbol
#正値だけ仮定する場合は、positive=Trueと指定
x = Symbol('x', positive=True)
if (x+5) > 5:
  print('x+5 : plus')
else:
  print('x+5 : minus')

#負値だけ仮定する場合は、negative=Trueと指定
x = Symbol('x', negative=True)
if (x+5) > 5:
  print('x+5 : plus')
else:
  print('x+5 : minus')

結果

x+5 : plus
x+5 : minus

7.3 関数の極限を求める

#Limitクラスのオブジェクトで関数の極限を求めます。
from sympy import Limit, Symbol, S #S:無限大や特別な値を定義するための使用する
x = Symbol('x')
print(Limit(1/x, x, S.Infinity)) #S.Infinity:無限大
print(Limit(1/x, x, 0, dir='-').doit()) #doit()で極限値を求める。dir='-'で負の方向を指定
print(Limit(1/x, x, 0, dir='+').doit()) #doit()で極限値を求める。dir='+'で正の方向を指定

結果

Limit(1/x, x, oo, dir='-')
-oo
oo

7.3.1 連続複利(Continuous Compound Interest)

7.3.2 瞬間変化率

7.4 関数の微分を求める

#7.4 関数の微分を求める

from sympy import Symbol, Derivative
t = Symbol('t')
St = 5*t**2 + 2*t + 8
print(Derivative(St, t))
print(Derivative(St, t).doit())
print(Derivative(St, t).doit().subs({t:1}))

結果

Derivative(5*t**2 + 2*t + 8, t)
10*t + 2
12

7.4.1 微分電卓

#微分電卓
from sympy import Symbol, Derivative, sympify, pprint
from sympy.core.sympify import SympifyError

def derivative(f, var):
  var = Symbol(var)
  d = Derivative(f, var).doit()
  pprint(d)


if __name__=='__main__':
  
  f = input('Enter a function: ')
  var = input('Enter the variable to differentiate with respect to: ')
  
  try:
    f = sympify(f)
  except SympifyError:
    print('Invalid input')
  else:
    derivative(f, var)

結果

# エラーになったが、以下が正しい結果で、再検証
Enter a function: 2*x**2 + 3*x + 1
Enter the varlable tO differentiate with respect to: x
4*x+3

7.4.2 偏微分を求める

結果

Enter a function: 2*x*y + x*y**2
Enter the varlable tO differentiate with respect to: x
4*x+3

『Pythonからはじめる数学入門』5章 集合と確率を操作する

f:id:kaeken:20171204234713p:plainPythonからはじめる数学入門』

5章 集合と確率を操作する

の解説です。

5.1 集合とは何か

集合(set)、要素(element)といったキーワードの意味は、高校数学で出てきていますのでここでは省略します。

以下、Pythonで集合の演算方法をみていきます。

5.1.1 集合の構成

まず、集合は、sympyのFiniteSetをimportして構成します。

from sympy import FiniteSet
s = FiniteSet(2,4,6)
print(s)

結果

{2, 4, 6}
# {} は集合を意味します

集合は、さまざまな要素をもつことができ、要素の個数は、len()で求められます。

from sympy import FiniteSet
from fractions import Fraction
s = FiniteSet(1,1.5, Fraction(1,5)) # さまざな数を要素にもてる
print(s)
print(len(s)) # 集合の濃度(cardinality)=要素の個数は、len()で求める

結果

{1/5, 1, 1.5}
3

集合の要素かどうかの判定方法は、in でチェックできます。

#5.1.1.1 要素判定

print(1 in s)
print(4 in s)

結果

True
False

また、空集合をつくる方法です。

#5.1.1.2 空集合を作る

s = FiniteSet()
s

結果

EmptySet()

リストやタプルから集合を作る場合は、可変長引数として渡します。

#5.1.1.3 リストやタプルから集合を作る

members = [1,2,3]
s = FiniteSet(*members) #*:可変長引数
s

結果

{1, 2, 3}

集合要素の重複は、取り除かれます。

#5.1.1.4 集合要素の重複と順序

from sympy import FiniteSet
members = [1,2,3,2]
FiniteSet(*members)

結果

{1, 2, 3}

また、順序は、一定になるとは限りません。

from sympy import FiniteSet
s = FiniteSet(1,2,3)
for member in s:
  print(member)

結果

1
2
3

集合が等しいかは、==で比較します。

from sympy import FiniteSet
s = FiniteSet(3,4,5)
t = FiniteSet(3,4,5)
s == t

結果

True

5.1.2 部分集合、上位集合、べき集合

一方の集合Aが、他方の集合Bに含まれる場合は、AはBの部分集合subsetといい、

その逆からみれば、BはAの上位集合supersetといいます。

また、完全に含まれている場合は、真部分集合proper subsetといい、逆は真上位集合proper supersetといいます。

#5.1.2 部分集合、上位集合、べき集合

s = FiniteSet(1)
t = FiniteSet(1,2)
print('subset')
print(s.is_subset(t))
print(t.is_subset(s))
print(s.is_subset(s))
print(t.is_subset(t))
print('superset')
print(s.is_superset(t))
print(t.is_superset(s))
print(s.is_superset(s))
print(t.is_superset(t))
print('proper_subset')
print(s.is_proper_subset(t))
print(t.is_proper_subset(s))
print(s.is_proper_subset(s))
print(t.is_proper_subset(t))
print('proper_superset')
print(s.is_proper_superset(t))
print(t.is_proper_superset(s))
print(s.is_proper_superset(s))
print(t.is_proper_superset(t))

結果

subset
True
False
True
True
superset
False
True
True
True
proper_subset
True
False
False
False
proper_superset
False
True
False
False

集合sのべき集合power setとは、sのすべての部分集合の集合を意味します。

s = FiniteSet(1,2,3)
ps = s.powerset()
print(ps)
print(len(ps))

結果

{EmptySet(), {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}}
8

5.1.3 集合演算

2つの集合の和union、積intersection、直積Cartesian productの演算は以下の通りです。

from sympy import FiniteSet
s = FiniteSet(1,3)
t = FiniteSet(3,6)
print('union')
print(s.union(t))
print('intersect')
print(s.intersect(t))
print('Cartesian product')
print(s*t)
for elem in s*t:
  print(elem)
print(s**3)
for elem in s**3:
  print(elem)

結果

union
{1, 3, 6}
intersect
{3}
Cartesian product
{1, 3} x {3, 6}
(1, 3)
(1, 6)
(3, 3)
(3, 6)
{1, 3} x {1, 3} x {1, 3}
(1, 1, 1)
(1, 1, 3)
(1, 3, 1)
(1, 3, 3)
(3, 1, 1)
(3, 1, 3)
(3, 3, 1)
(3, 3, 3)

5.2 確率

5.2.1 事象Aまたは事象Bの確率

5.2.2 事象Aおよび事象Bの確率

5.2.3 乱数生成

5.2.4 非一様乱数

『Pythonからはじめる数学入門』4章 SymPyで代数と式を計算する

f:id:kaeken:20171203090308p:plainPythonからはじめる数学入門』

4章 SymPyで代数と式を計算する

の解説です。

いままでは、数値計算でしたが、

xやyといった代数においては、

式の計算(symbolic math)が必要です。

Pythonでは、SymPyを使って式の計算をおこないます。

以下は、SymPyのリファレンスです。

SymPy

また、ブラウザ上で、SymPyの動作を確認できます。

SymPy Live

表示された数式を右クリックすると、Tex記法などに変換できます。

f:id:kaeken:20171203090224p:plain f:id:kaeken:20171203090308p:plain

4.1 式の記号と記号演算を定義する

SymPyでは、以下のとおり、記号を使って数式を表現します。

from sympy import Symbol
x = Symbol('x') #文字列xを用いてSymbolクラスのオブジェクトを作成
print(x + x + 1)

from sympy import symbols
x,y,z = symbols('x,y,z')
print((x+2)*(y+3)*(z+4))

結果

2*x + 1
(x + 2)*(y + 3)*(z + 4)

4.2 式を扱う

4.2.1 式の因数分解と展開

因数分解はfactor()を使い、展開はexpand()を使います。

from sympy import symbols
x,y = symbols('x,y')

from sympy import factor, expand
expr = x**2 - y**2

factors = factor(expr)
print('factors:{0}'.format(factors))

expand_result = expand(factors)
print('expand:{0}'.format(expand_result))

結果

factors:(x - y)*(x + y)
expand:x**2 - y**2

4.2.2 プリティプリント

式をみやすく出力したい場合は、pprint()を使います。

expr = x*x + 2*x*y + y*y
print('expr:{0}'.format(expr))

from sympy import pprint
pprint(expr, use_unicode=True)

結果

expr:x**2 + 2*x*y + y**2
 2            2
x  + 2⋅x⋅y + y 

4.2.3 値に代入する

式に値を代入するには、subs()を使います。

from sympy import symbols
x,y = symbols('x,y')
expr = x*x + x*y + x*y + y*y
res = expr.subs({x:1, y:2})
print(res)

結果

9

項の中の記号を別の式で表すこともできます。

from sympy import symbols
x,y = symbols('x,y')
expr = x*x + x*y + x*y + y*y
res = expr.subs({x:y-1})
print(res)

結果

y**2 + 2*y*(y - 1) + (y - 1)**2

4.2.4 文字列を数式に変換する

input()で入力された文字列を数式に変換する方法です。

from sympy import sympify
expr = input('input: ')
input: (入力した式)y**2 + 2*y*(y - 1) + (y - 1)**2
expr =sympify(expr)
print(2*expr)

結果

2*x**3 + 2*x**2 + 10*x

4.3 方程式を解く

4.3.1 2次方程式を解く

4.3.2 1変数を他の変数について解く

4.3.3 連立方程式を解く

4.4 SymPyを使ってプロットする

4.4.1 ユーザが入力した式をプロットする

4.4.2 複数の関数をプロットする

『Pythonからはじめる数学入門』3章 データを統計量で記述する

f:id:kaeken:20171203085006p:plainPythonからはじめる数学入門』

3章 データを統計量で記述する

の解説です。

機械学習では、

統計がよく出てくるので、

ここでは、統計の基本をPythonで学びます。

3.1 平均を求める

まずは、平均値を求める関数です。

def calculate_mean(numbers):
  s = sum(numbers) #合計
  N = len(numbers) #要素数
  mean = s/N #平均
  
  return mean

if __name__ == '__main__':
  datalist = [100,60,70,900,100,200,500,500,503,600,1000,1200]
  mean = calculate_mean(datalist)
  N = len(datalist)
  print('要素数:{0}, 平均:{1}'.format(N, mean))

結果

要素数:12, 平均:477

3.2 中央値を求める

昇順にならべたリストの中央の要素が中央値です(リストが偶数個なら中央2要素の平均)。

中央値を求める関数です。

def calculate_median(numbers): #中央値計算
  N = len(numbers) #要素数
  numbers.sort() #昇順に並び替え
  
  if N % 2 == 0:
    m1 = int(N/2) - 1 # 整数に変換して位置合わせ
    m2 = int((N/2) + 1) -1
    median = (numbers[m1] + numbers[m2])/2
  else:
    m = (N+1)/2
    m = int(m) - 1
    median = numbers[m]
  
  return median

if __name__ == '__main__':
  datalist = [100,60,70,900,100,200,500,500,503,600,1000,1200]
  median = calculate_median(datalist)
  N = len(datalist)
  print('N:{0}, 中央値:{1}'.format(N, median))
  datalist.sort()
  print(datalist)

結果

N:12, 中央値:500
[60, 70, 100, 100, 200, 500, 500, 503, 600, 900, 1000, 1200]

3.3 最頻値を求め度数分布表を作る

最頻値は、もっとも多く出現する値です。

3.3.1 一番多い要素を見つける

要素の個数が多い順にリストを返すmost_common()を使います。

datalist = [4,2,1,2,3,4,2]
from collections import Counter
c = Counter(datalist)
print(c.most_common()) #要素の個数が多い順に表示
print(c.most_common(2)) #上位2番目までの要素のみ表示

結果

[(2, 3), (4, 2), (1, 1), (3, 1)]
[(2, 3), (4, 2)]

3.3.2 最頻値を探す

最頻値を返す関数です。

from collections import Counter

def calculate_mode(numbers):
  c = Counter(numbers)
  mode = c.most_common(1)
  return mode[0][0]

if __name__ == '__main__':
  scores = [7,8,6,7,5,3,3,3,5,6,1,9,1,1,2,4,0,2,3,5,2]
  mode = calculate_mode(scores)
  print('最頻値:{0}'.format(mode))

結果

最頻値:3

3.3.3 度数分布表を作る

数のリストの度数分布表の求め方です。

from collections import Counter

def frequency_table(numbers):
  table = Counter(numbers)
  print('Number | Frequency')
  for number in table.most_common():
    print('{0} | {1}'.format(number[0], number[1]))

if __name__ == '__main__':
  scores = [7,8,6,7,5,3,3,3,5,6,1,9,1,1,2,4,0,2,3,5,2]
  mode = frequency_table(scores)

結果

Number | Frequency
3 | 4
1 | 3
2 | 3
5 | 3
6 | 2
7 | 2
0 | 1
4 | 1
8 | 1
9 | 1

3.4 散らばりを測る

散らばり(dispersion)とは、 データセットで数がどれだけ 平均から離れているかの統計値です。

3.4.1 数集合の範囲を決める

数集合の範囲を求める処理です。

def find_range(numbers):
  lowest = min(numbers)
  highest = max(numbers)
  r = highest - lowest
  return lowest, highest, r

if __name__ == '__main__':
  dataset = [100,60,70,900,100,200,500,500,503,600,1000,1200]
  lowest, highest, r = find_range(dataset)
  print('Lowest:{0} Highest:{1} Range:{2}'.format(lowest, highest, r))

結果

Lowest:60 Highest:1200 Range:1140

3.4.2 分散と標準偏差を求める

分散(variance)とは、値の散らばり度合いです。

分散が大きければ、値が平均から大きく離れて、小さければ、値が平均近くにかたまっています。

def calculate_mean(numbers):
  s = sum(numbers) #合計
  N = len(numbers) #要素数
  mean = s/N #平均
  
  return mean

def find_differences(numbers):
  mean = calculate_mean(numbers)
  diff = []
  
  for num in numbers:
    diff.append(num - mean)
  return diff

def calculate_variance(numbers): #分散
  diff = find_differences(numbers)
  squared_diff = []
  for d in diff:
    squared_diff.append(d**2)
  sum_squared_diff = sum(squared_diff)
  variance = sum_squared_diff / len(numbers)
  return variance

if __name__ == '__main__':
  datalist = [100,60,70,900,100,200,500,500,503,600,1000,1200]
  variance = calculate_variance(datalist) #分散
  print('variance:{0}'.format(variance))
  
  std = variance**0.5 #標準偏差
  print('std:{0}'.format(std))

結果

variance:141047
std:375.562245174

3.5 2つのデータセットの相関を計算する

相関とは、2つのデータセットの関係性です。

相関係数とは、線形的な関係性を-1から1の範囲で示す統計量です。非線形関係については、別の測度が必要です。

相関係数0:線形相関がない

相関係数+1:強い正の線形相関がある

相関係数−1:強い負の線形相関がある

3.5.1 相関係数を計算する

相関係数を計算するためには、2つのデータセットの対応する要素の対を返すzip()関数を使います。

dataset1 = [1,2,3]
dataset2 = [4,5,6]
for x, y in zip(dataset1,dataset2):
  print(x,y)

結果

(1, 4)
(2, 5)
(3, 6)

相関係数の計算式は、以下を参照してください。

相関係数 - Wikipedia

相関係数を求める処理は以下の通りです。

def find_corr_x_y(x,y):
  n = len(x)
  prod = []
  for xi,yi in zip(x,y):
    prod.append(xi*yi)
  sum_prod_x_y = sum(prod)
  sum_x = sum(x)
  sum_y = sum(y)
  squared_sum_x = sum_x**2
  squared_sum_y = sum_y**2
  x_square = []
  for xi in x:
    x_square.append(xi**2)
  x_square_sum = sum(x_square)
  y_square = []
  for yi in y:
    y_square.append(yi**2)
  y_square_sum = sum(y_square)
  
  numerator = n*sum_prod_x_y - sum_x*sum_y
  denominator_term1 = n*x_square_sum - squared_sum_x
  denominator_term2 = n*y_square_sum - squared_sum_y
  denominator = (denominator_term1*denominator_term2)**0.5
  correlation = numerator/denominator
  
  return correlation

if __name__ == '__main__':
  data1 = [1,2,3]
  data2 = [1,2,3]
  corr = find_corr_x_y(data1,data2)
  print('data1 data2 correlation:{0}'.format(corr))

  data3 = [1,2,3]
  data4 = [3,2,1]
  corr = find_corr_x_y(data3,data4)
  print('data3 data4 correlation:{0}'.format(corr))

  data5 = [-93831,29999,8188]
  data6 = [-1,-2,1]
  corr = find_corr_x_y(data5,data6)
  print('data5 data6 correlation:{0}'.format(corr))

結果

data1 data2 correlation:1.0
data3 data4 correlation:-1.0
data5 data6 correlation:0.0243875472264

3.5.2 高校の成績と大学入試の点数

2つのデータセットのプロットを散布図で表現すれば、ビジュアルで理解できます。

3.6 散布図

散布図は以下のように表示します。

x = [10,20,30,40]
y = [20,40,60,80]
import matplotlib.pyplot as plt
plt.scatter(x,y)
plt.show()

f:id:kaeken:20171203081027p:plain

『Pythonからはじめる数学入門』2章 データをグラフで可視化する

Pythonからはじめる数学入門』

2章 データをグラフで可視化する

の解説です。 www.oreilly.co.jp

f:id:kaeken:20171201232820p:plain 機械学習で数値データを提示する際には、

グラフを用いることが多いです。

今回は、

Pythonでグラフを使う方法についてご説明します。

2章 データをグラフで可視化する

2.1 デカルト座標平面を理解する

デカルト座標平面とは、いわゆるx-y平面のことです。

高校数学で出てくるので、用語のみ記載します。

座標coordinates
原点origin
集合set
プロットplot
グラフgraph

2.2 リストとタプルの操作

リスト:可変的な要素のかたまり(あとで変更できる)

タプル:固定された要素のかたまり(あとで変更できない)

2.2.1 リストやタプルで繰り返す

リストやタプルはfor文で繰り返すことができます。

>>> list = [1,2,3]

>>> for item in list:
...     print(item)
...
1
2
3

>>> for index, item in enumerate(list):
...     print(index, item)
...
(0, 1)
(1, 2)
(2, 3)

2.3 matplotlibでグラフを作る

matplotlibは、Pythonのグラフ描画パッケージです。

インストール方法は、次のコマンドでインストールするか、 別途「matplotlib インストール」などで検索してみてください。

pip install matplotlib

さっそく以下のコードを打ち込んでいきますが、

#点(1,2), (2,4), (3,6)をプロット
x = [1,2,3]
y = [2,4,6]

from pylab import plot, show
plot(x, y)
show()

以下は、説明でにグラフ描画を表示するため、 コマンドラインではなく、 Jupyter Notebookを使って実行していきます。

上記の実行結果です。 f:id:kaeken:20171201221735p:plain

2.3.1 グラフで点を作る

プロットを明示する場合です。

plot(x, y, marker='o')

実行結果です。 f:id:kaeken:20171201222133p:plain

マーカーのみ表示する場合は、以下のように記載します。

plot(x, y, 'o')

f:id:kaeken:20171201222458p:plain

2.3.2 ニューヨーク市の年間平均気温をグラフ化する

複数のプロットをしていけば、データの傾向をつかめます。

nyc_temp=[53.9,56.3,56.4,53.4,54.5,55.8,56.8,55.0,55.3,54.0,56.7,56.4,57.3]
plot(nyc_temp, marker='o')

f:id:kaeken:20171201222912p:plain

x軸に年など特定の値を設定する方法です。

years = range(2000,2013)
plot(years, nyc_temp, marker='o')

f:id:kaeken:20171201223134p:plain

2.3.3 ニューヨーク市の月間気温傾向を比較する

複数のグラフを重ね合わせる方法です。

#データはダミー
y2000=[53.9,56.3,56.4,53.4,54.5,55.8,56.8,55.0,55.3,54.0,56.7,56.4]
y2006=[56.9,56.1,46.4,51.4,56.5,65.8,56.8,55.3,59.3,44.0,59.7,56.1]
y2012=[51.9,59.3,51.4,52.4,53.5,59.8,51.8,52.0,57.3,53.0,56.2,66.4]
months = range(1,13)
plot(months, y2000, months, y2006, months, y2012, marker='o')

from pylab import legend
legend([2000,2006,2012])

f:id:kaeken:20171201224222p:plain legend()で、凡例の指定ができます。

細かい引数の指定方法は、以下を参照してください。

legend and legend_handler — Matplotlib 2.1.0 documentation

2.3.4 グラフのカスタマイズ

タイトル、X軸名、Y軸名など、

他にカスタマイズする方法は、以下のとおりです。

y2000=[53.9,56.3,56.4,53.4,54.5,55.8,56.8,55.0,55.3,54.0,56.7,56.4]
y2006=[56.9,56.1,46.4,51.4,56.5,65.8,56.8,55.3,59.3,44.0,59.7,56.1]
y2012=[51.9,59.3,51.4,52.4,53.5,59.8,51.8,52.0,57.3,53.0,56.2,66.4]
months = range(1,13)
plot(months, y2000, months, y2006, months, y2012, marker='o')

from pylab import legend
legend([2000,2006,2012])

from pylab import title, xlabel, ylabel
#title
title('matplotlib title')

#xlabel
xlabel('Month')

#ylabel
ylabel('Temp')

f:id:kaeken:20171201225039p:plain

また、

axis()によって、軸の最小値、最大値を指定できます。

Y軸の最小値を0にした場合です。

y2000=[53.9,56.3,56.4,53.4,54.5,55.8,56.8,55.0,55.3,54.0,56.7,56.4]
y2006=[56.9,56.1,46.4,51.4,56.5,65.8,56.8,55.3,59.3,44.0,59.7,56.1]
y2012=[51.9,59.3,51.4,52.4,53.5,59.8,51.8,52.0,57.3,53.0,56.2,66.4]
months = range(1,13)
plot(months, y2000, months, y2006, months, y2012, marker='o')

from pylab import legend
legend([2000,2006,2012])

from pylab import title, xlabel, ylabel
title('matplotlib title')
xlabel('Month')
ylabel('Temp')

from pylab import axis
axis(ymin=0)

f:id:kaeken:20171201232626p:plain

また、

X軸の最小値・最大値、Y軸の最小値・最大値を以下の通り指定できます。

y2000=[53.9,56.3,56.4,53.4,54.5,55.8,56.8,55.0,55.3,54.0,56.7,56.4]
y2006=[56.9,56.1,46.4,51.4,56.5,65.8,56.8,55.3,59.3,44.0,59.7,56.1]
y2012=[51.9,59.3,51.4,52.4,53.5,59.8,51.8,52.0,57.3,53.0,56.2,66.4]
months = range(1,13)
plot(months, y2000, months, y2006, months, y2012, marker='o')

from pylab import legend
legend([2000,2006,2012])

from pylab import title, xlabel, ylabel
title('matplotlib title')
xlabel('Month')
ylabel('Temp')

from pylab import axis
axis([0,13,0,100])

f:id:kaeken:20171201232820p:plain

最後に、対話シェルではなく、プログラムの一部として、グラフを使う場合は、

pylabではなくpyplotを使います。

import matplotlib.pyplot as plt
def create_graph():
    x  = [1,2,3]
    y = [2,4,6]
    plt.plot(x,y)

if __name__ == '__main__':
  create_graph()

f:id:kaeken:20171201233326p:plain

2.3.5 プロットの保存

グラフを保存するには、savefig()を使います。

from pylab import plot,savefig
x = [1,2,3]
y = [2,4,6]
plot(x,y)
savefig('mygraph.png')

2.4 式をプロットする

今までのご説明は、

すでにプロットするデータがあった場合ですが、

数式からプロットする方法があります。

2.4.1 ニュートン万有引力の法則

詳細説明は省略しますが、イメージとして以下のようなグラフを描画できます。

import matplotlib.pyplot as plt

def draw_graph(x,y):
  plt.plot(x, y, marker='o')
  plt.xlabel('Distance in meters')
  plt.ylabel('Gravitational force in newtons')
  plt.title('Gravitational force and distance')
  plt.show()

def generate_F_r():
  r = range(100, 1001, 50)
  F = []
  G = 6.674*(10**-11)
  m1 = 0.5
  m2 = 1.5
  for dist in r:
    force = G*(m1*m2)/(dist**2)
    F.append(force)
  draw_graph(r, F)

if __name__=='__main__':
  generate_F_r()

f:id:kaeken:20171201234548p:plain

2.4.2 投射運動

以上、

Pythonからはじめる数学入門』2章 データをグラフで可視化する

の解説でした。