機械学習を使って、天気予報をする。第2回

この記事は、Weather UndergroundのAPIサービスから収集したデータを基に、Pythonで機械学習を使って米国ネブラスカ州リンカーン市の天気気温を予測する3部構成のシリーズの前回の記事の続きとなります。

このシリーズの最初の記事「Using Machine Learning to Predict the Weather: パート1では、Weather Undergroundからデータを抽出し、パースし、クリーニングする方法を説明しました。

このシリーズで紹介する各記事のトピックの概要については、前の記事の紹介をご覧ください。

この記事の焦点は、前回の記事で作成したデータセットに基づいて、将来の日平均気温値を予測するための厳密な線形回帰モデルを構築するために必要なプロセスと手順について説明することです。

線形回帰モデルを構築するために、機械学習業界で重要な2つのPythonライブラリを使用することを説明します。

Scikit-LearnとStatsModelsです。

連載3回目の記事「機械学習を使って天気予報をする。

第3回では、GoogleのTensorFlowを使ってニューラルネットワークを構築し、将来の日平均気温を予測するために必要なプロセスと手順について説明します。

この方法を用いると、線形回帰モデルと結果を比較することができます。

データセットを再認識する

この GitHub リポジトリには、Weather Underground API.ipynb というファイル名の Jupyter Notebook があり、この記事と最終記事で扱うデータセットを収集するために必要なステップバイステップのアクションが記述されています。

さらに、このリポジトリには、end-part1_df.pklというPandas DataFrameのpickleファイルがあります。

もしあなたが、前の記事で説明したデータの収集、処理、クリーニングという少し辛い経験をすることなく、一緒について行きたいなら、pickleファイルを引き出して、次のコードを使って、このセクションで使うためにデータをPandas DataFrameに戻してデシリアライズしてください。

import pickle
with open('end-part1_df.pkl', 'rb') as fp:
    df = pickle.load(fp)


もし「No module named ‘pandas.indexes’」というエラーが出たら、それはこの記事を書いた時に使っていたpandasのバージョン(v0.18.1)よりも新しいものを使っている可能性があるからです。

これを避けるために、私はその後、パート1の最後のデータを含むCSVファイルをレポに含め、代わりに以下のコードを使って読み込むことができるようにしました。

import pandas as pd
df = pd.read_csv('end-part2_df.csv').set_index('date')


経常最小二乗法による線形回帰の背景

線形回帰は、1つ以上の予測因子(Xの独立変数)に基づいて結果(Y、別名従属変数)を予測するために、線形関係に関する一連の仮定と数値技術を適用し、ある程度の不確かさで予測因子値のみを与えて結果を予測するモデル(数式)を確立することを最終目的としています。

線形回帰モデルの一般化された式は次のとおりです。


ŷ = β0 + β1 * x1 + β2 * x2 + ... + β(p-n) x(p-n) + Ε


ここで

  • l_177` は予測される結果変数(従属変数)である.
  • xj` は,j = 1,2,…, p-1 パラメータの予測変数(独立変数)である.
  • β0は切片または各xjがゼロに等しいときのl_177` の値である。
  • βjは、対応するxjのいずれかを 1 単位変化させたときの_177` の変化量である。
  • Εは、予測値_177iと実際の値yi` との差に関連するランダムな誤差項である。

線形回帰の式の最後の項は非常に重要である。

線形回帰モデルを構築する最も基本的な方法は、最小化項を最小化するβj`の値の組み合わせを見つける最小二乗法として知られるアルゴリズムに依存する。

モデルの機能選択

線形回帰手法で必要とされる主要な仮定は、従属変数と各独立変数の間に線形関係があることです。

我々の独立変数(今は平均温度とします)と他の独立変数の間の線形性を評価する1つの方法は、ピアソン相関係数を計算することです。

ピアソン相関係数(r)は、同じ長さの配列間の線形相関の量を測定し、-1 から 1 の範囲の値を出力するものである。

0から1までの相関値は、ますます強い正の相関を表しています。

つまり、2つのデータ系列のうち、一方のデータ系列の値が他方のデータ系列の値と同時に増加し、両者の増加の度合いが等しくなると、ピアソン相関の値が1に近づくことから、正の相関があることを意味します。

相関値が0~-1の場合は、一方の系列の値が上昇すると、他方の系列の値が下降するが、系列間の大きさの変化が等しくなる(向きが逆になる)と相関値が-1に近づくという逆相関、つまり負の相関があるとされます。

ピアソン相関の値が0に近いほど線形関係が弱く、0に近づくほど弱くなることを示唆する。

相関係数の強さのレベルの明確な境界線については、統計学者や統計書の間でも意見が分かれるところです。

しかし、一般に受け入れられている相関の強さの分類は、以下のようなものであることがわかりました。

| 相関値|解釈|相関係数
| — | — |
| 0.8 – 1.0|非常に強い|0.6 – 0.8
| 0.6 – 0.8|強い|0.4 – 0.6
| 0.4〜0.6|中程度|0.2〜0.4|低レベル|低レベル
| 0.2〜0.4|弱い|0.0〜0.2|弱い
| 0.0〜0.2|非常に弱い|0.0〜0.2|非常に弱い

このデータの相関を評価するために、Pandas DataFrameオブジェクトの corr() メソッドを呼び出します。

この corr() メソッド呼び出しに連鎖して、興味のある列 (“meantempm”) を選択し、結果の Pandas Series オブジェクトに別のメソッド呼び出し sort_values() を再び連鎖させることができます。

これは、最もネガティブな相関から最もポジティブな相関までの相関値を出力します。

df.corr()[['meantempm']].sort_values('meantempm')


| meanempm
| — | — |
| maxpressurem1 | -0.519699 | -0.519699
| maxpressurem
2 | -0.425666 | -0.425666
| maxpressurem_3 | -0.408902 | -0.408902 | -0.408902
| meanpressurem_1 | -0.365682 | -0.365682
| meanpressurem_2 | -0.269896 | -0.269896
| 平均圧m_3|-0.263008|です。

| minpressurem_1 | -0.201003
| minhumidity_1 | -0.148602
| minhumidity_2 | -0.143211 | -0.143211
| minhumidity_3 | -0.118564 | -0.118564
| minpressurem_2 | -0.104455 | -0.118564
| minpressurem_3 | -0.102955
| precipm_2 | 0.084394
| precipm_1 | 0.086617 | 0.086617
| precipm_3 | 0.098684となります。

| maxhumidity_1 | 0.132466 | (最大湿度
| maxhumidity_2 | 0.151358のような。

| maxhumidity_3 | 0.167035 | (湿度の最大値
| maxdewptm_3 | 0.829230
| maxtempm_3 | 0.832974
| mindewptm3 | 0.833546
| meandewptm
3 | 0.834251
| mintempm__3 | 0.836340
| maxdewptm2 | 0.839893
| meandewptm
2 | 0.848907
| mindewptm_2 | 0.852760
| meantempm_3 | 0.854320
| meantempm__3 | 0.855662
| maxtempm_2 | 0.863906 | (英語版のみ
| meantempmptm__2 | 0.881221
| maxdewptm_1 | 0.887235 | 1.0
| meandewptm_1 | 0.896681 | 0.896681
| mindewptm_1 |0.899000 |0.899000
| mintempm_1 | 0.905423 | (※英語版のみ。

| maxtempm_1 | 0.923787 ||Meanyempm_1
| meantempm_1 | 0.937563 | (※1)。

| mintempm|0.973122|です。

この線形回帰モデルに含める特徴を選択する際に、中程度または低い相関係数を持つ変数を含めることに、少し寛容でない側でエラーにしたいと思います。

そこで、相関値の絶対値が0.6より小さい特徴量を削除することにします。

また、変数「mintempm」と「maxtempm」は、予測変数「m meantempm」と同じ日のものなので、それらも削除します(つまり、最小温度と最大温度がすでに分かっていれば、私の予測の答えはすでに出ているのです)。

この情報により、私は興味のある変数のみを含む新しいDataFrameを作成することができます。

predictors = ['meantempm_1',  'meantempm_2',  'meantempm_3', 
              'mintempm_1',   'mintempm_2',   'mintempm_3',
              'meandewptm_1', 'meandewptm_2', 'meandewptm_3',
              'maxdewptm_1',  'maxdewptm_2',  'maxdewptm_3',
              'mindewptm_1',  'mindewptm_2',  'mindewptm_3',
              'maxtempm_1',   'maxtempm_2',   'maxtempm_3']
df2 = df[['meantempm'] + predictors]


関係性の可視化

私を含むほとんどの人は、パターンを評価し検証するために視覚を見ることに慣れているので、私は、実際に線形関係があることを自分自身に証明するために、これらの選択された予測因子のそれぞれをグラフにするつもりです。

これを行うために、私はmatplotlibのpyplotモジュールを利用します。

このプロットでは、従属変数 “meenempm “が、18個の予測変数のプロットに沿って一貫したY軸になるようにしたいと思います。

これを達成する1つの方法は、プロットのグリッドを作成することです。

Pandasには、scatter_plot()という便利なプロット関数がありますが、プロットがN×N行列(我々の場合は18×18)になり、データの詳細を見るのが難しくなるので、一般的には5変数くらいまでしかない時にしか使いません。

その代わり、グラフのわかりやすさを犠牲にしないために、3列6行のグリッド構造を作ることにします。

import matplotlib
import matplotlib.pyplot as plt
import numpy as np


%matplotlib inline


# manually set the parameters of the figure to and appropriate size
plt.rcParams['figure.figsize'] = [16, 22]


# call subplots specifying the grid structure we desire and that 
# the y axes should be shared
fig, axes = plt.subplots(nrows=6, ncols=3, sharey=True)


# Since it would be nice to loop through the features in to build this plot
# let us rearrange our data into a 2D array of 6 rows and 3 columns
arr = np.array(predictors).reshape(6, 3)


# use enumerate to loop over the arr 2D array of rows and columns
# and create scatter plots of each meantempm vs each feature
for row, col_arr in enumerate(arr):
    for col, feature in enumerate(col_arr):
        axes[row, col].scatter(df2[feature], df2['meantempm'])
        if col == 0:
            axes[row, col].set(xlabel=feature, ylabel='meantempm')
        else:
            axes[row, col].set(xlabel=feature)
plt.show()


上のプロットから、残りのすべての予測変数が応答変数(”meanempm”)と良い線形関係を示していることがわかります。

さらに、関係性がすべて一様にランダムに分布していることも注目すべき点です。

これは、扇形や円錐形のない値の広がりに、比較的均等な変動があるように見えるということです。

点に沿った広がりの均一なランダム分布も、最小二乗法による線形回帰の重要な仮定です。

ステップワイズ回帰を用いたロバストモデルの構築

ロバストな線形回帰モデルは、含めるべき意味のある、統計的に有意な予測変数を選択するために、統計的検定を利用する必要があります。

統計的に有意な特徴を選択するために、私はPythonの statsmodels ライブラリを利用します。

しかし、statsmodelsライブラリの実用的な実装に入る前に、一歩下がって、このアプローチを取る理論的な意味と目的について説明したいと思います。

分析プロジェクトで線形回帰のような統計手法を使用する際の重要な側面は、研究対象のデータについて立てた仮定の重要性を検証するための仮説検定の確立とテストです。

様々な仮定に対する線形回帰モデルの頑健性を検証するために、数多くの仮説検定が開発されています。

そのような仮説検定の1つは、含まれる予測変数のそれぞれの有意性を評価することです。

パラメータβjの有意性についての仮説検定の正式な定義は、以下の通りである。

  • H0:βj = 0`, 帰無仮説は、予測変数が結果変数の値に影響を与えないというものである。
  • Ha:βj ≠ 0`, 偏仮説は,予測変数が結果変数の値に有意な効果を持つことである.

選択されたしきい値 Αで,各βj が単純な無作為の偶然を超えて有意である可能性を評価する確率の検定を用いることにより,より頑健なモデルをもたらす含めるべき変数をより厳しく選択することができる.

しかし、多くのデータセットでは、変数間に相互作用が発生し、これらの単純な仮説検定の解釈を誤らせる可能性がある。

線形回帰モデルにおける任意の1つの変数の有意性に対する交互作用の効果を検定するために、ステップ・ワイズ回帰として知られるテクニックがしばしば適用されます。

ステップ・ワイズ回帰を使用して、モデルから変数を追加または削除して、結果のモデルで各変数の統計的有意性を評価します。

この記事では、バックワード・エリミネーションとして知られるテクニックを使用し、興味のあるすべての変数を含む完全にロードされた一般的なモデルから始めます。

バックワード・エリミネーションは、次のように機能します。

  1. ある変数がモデルに残るべきかどうかを決定するために、仮説を検定する有意水準 Α を選択します。
  2. すべての予測変数でモデルを適合させる
    1. βj 係数の p-値を評価し、最大の p-値を持つものについて、p-値 > Α があればステップ 4 に進み、なければ最終モデルがある。
  3. ステップ3で識別された予測変数を除去します。
    1. 再びモデルを適合させますが、今度は、除去された変数を除いて、ステップ3に戻って循環させます。

それでは、上記のステップに従って、statsmodelsを使用して、この完全にロードされた一般化モデルを構築しましょう。

# import the relevant module
import statsmodels.api as sm


# separate our my predictor variables (X) from my outcome variable y
X = df2[predictors]
y = df2['meantempm']


# Add a constant to the predictor variable set to represent the Bo intercept
X = sm.add_constant(X)
X.ix[:5, :5]


| const | meantempm_1 | meantempm__2 | meantempm__3 | mintempm___1

| 2015-01-04 | 1.0 | -4.0 | -6.0 | -6.0 | -13.0 |
| 2015-01-05 | 1.0 | -14.0 | -4.0 | -6.0 | -18.0 |
| 2015-01-06 | 1.0 | -9.0 | -14.0 | -4.0 | -14.0 |
| 2015-01-07 | 1.0 | -10.0 | -9.0 | -14.0 | -14.0 |
| 2015-01-08 | 1.0 | -16.0 | -10.0 | -9.0 | -19.0 |

# (1) select a significance value
alpha = 0.05


# (2) Fit the model
model = sm.OLS(y, X).fit()


# (3) evaluate the coefficients' p-values
model.summary()


summary()`を呼び出すと、Jupyterノートブックに以下のデータが出力されます。

OLS回帰結果| Dep.変数: | R二乗: | 0.895 |
| モデル | OLS|Adj.R-squared: | 0.893 |
| 方法 | 最小二乗法|F統計量。

| 462.7 |
| 日付 | 2017年11月16日(木)| Prob (F-statistic): | 0.00 |
| 時間 | 20:55:25|対数尤度。

| -2679.2 |
| 観察数: | 997|AIC。

| 5396. |
| Df残差: | 978|BIC。

| 5490. |
| Dfモデル。

| 18 | | |
| 共分散タイプ。

| — | — | — | — | — | — | — |
| | coef | std err | t | P>|t| | [0.025 | 0.975] | [0.025 | 0.975] | [0.025 | 0.975] | [0.025 | 1.0769
| 1.0769|0.526|2.049|0.041|0.046|2.108|||meensempmgmgm_1
| meantempm_1 | 0.1047 | 0.287 | 0.364 | 0.716 | -0.459 | 0.669
| meantempm_2 | 0.3512 | 0.287 | 1.225 | 0.221 | -0.211 | 0.914
| meantempm_3 | -0.1084 | 0.286 | -0.379 | 0.705 | -0.669| 0.453
| mintempm_1 | 0.0805 | 0.149 | 0.539 | 0.590 | -0.213 | 0.373
| mintempm_2 | -0.2371 | 0.149 | -1.587 | 0.113 | -0.530 | 0.056
| mintempmxx_3 | 0.1521 | 0.148 | 1.028 | 0.304 | -0.138 | 0.443
| MEANDEWPTMENT_THERE_1 | -0.0418 | 0.138 | -0.304 | 0.761 | -0.312 | 0.228|||MEANDEWPTMENT_THERE_1
| meandewptm2 | -0.0121 | 0.138 | -0.088 | 0.930 | -0.282 | 0.258 ||||Meandewptm3 | -0.0121 | 0.138 | -0.302 | 0.258
| meandewptm_3 | -0.0060 | 0.137 | -0.044 | 0.965 | -0.275 | 0.263
| maxdewptm1 | -0.1592 | 0.091 | -1.756 | 0.079 | -0.337 | 0.019
| maxdewptm
2 | -0.0113 | 0.091 | -0.125 | 0.900 | -0.189 | 0.166
| maxdewptm_3 | 0.1326 | 0.089 | 1.492 | 0.136 | -0.042 | 0.307
| mindewptm
_1 | 0.3638 | 0.084 | 4.346 | 0.000 | 0.200 | 0.528
| mindewptm_2 | -0.0119 | 0.088 | -0.136 | 0.892 | -0.184 | 0.160

SciKit-LearnのLinearRegressionモジュールを使って天気予報を行う。

統計的に意味のある予測因子(特徴量)を選択するステップを経たので、SciKit-Learn を使って予測モデルを作成し、平均気温を予測する能力をテストすることができるようになりました。

SciKit-Learnは非常に定評のある機械学習ライブラリで、産業界と学術界の両方で広く利用されています。

SciKit-Learnが非常に優れている点は、多くの数値計算技術やアルゴリズムにおいて「fit」、「predict」、「test」という非常に一貫したAPIを維持しているため、非常にシンプルに使用できる点です。

この一貫したAPI設計に加え、SciKit-Learnには多くの機械学習プロジェクトに共通するデータを処理するための便利なツールがいくつか付属しています。

まず、SciKit-Learnを使って、sklearn.model_selectionモジュールから train_test_split() 関数をインポートし、データセットをテストとトレーニングに分割するところから始めましょう。

ここでは、トレーニングとテストのデータセットを 80% トレーニングと 20% テストに分割し、random_state を 12 に設定して、私と同じようにランダムにデータを選択するようにします。

この random_state パラメータは、結果の再現性を高めるために非常に有効です。

# (3) cont. - Identify the predictor with the greatest p-value and assess if its > our selected alpha.
#             based off the table it is clear that meandewptm_3 has the greatest p-value and that it is
#             greater than our alpha of 0.05


# (4) - Use pandas drop function to remove this column from X
X = X.drop('meandewptm_3', axis=1)


# (5) Fit the model 
model = sm.OLS(y, X).fit()


model.summary()


model = sm.OLS(y, X).fit()
model.summary()


次に行うべきことは、学習データセットを用いて回帰モデルを構築することです。

そのために、 sklearn.linear_model モジュールから LinearRegression クラスをインポートして使用します。

前述したように、scikit-learn は数多くの数値計算技術に共通の fit()predict() API を実装しており、ライブラリの使い勝手が非常に良くなっています。

from sklearn.model_selection import train_test_split


# first remove the const column because unlike statsmodels, SciKit-Learn will add that in for us
X = X.drop('const', axis=1)


X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=12)


from sklearn.linear_model import LinearRegression


上の数行のコードでわかるように、線形回帰予測モデルを構築するために scikit-learn を使うのはとても簡単です。

このライブラリは、簡単にモデルを適合させ、関心のある結果について予測する能力において、まさに輝くところです。

モデルの妥当性を解釈的に理解するために、私はリグレッサーモデルの score() 関数を使い、モデルが結果変数である平均気温で観測された分散の約90%を説明できることを決定しました。

さらに、私は sklearn.metrics モジュールの mean_absolute_error()median_absolute_error() を使って、予測値が平均で約3℃、半分の時間で約2℃ずれていることを判断しました。

リソース

このチュートリアルで使用されているツール、機械学習技術、データ分析について学びたいですか?ここでは、そのための素晴らしいリソースをいくつか紹介します。

  • PandasとPythonを使ったデータ分析
  • ディープラーニングの前提条件 Pythonの線形回帰
  • データサイエンスと機械学習のためのPython Bootcamp

結論

この記事では、線形回帰機械学習アルゴリズムを使用して、前の記事で収集したデータに基づいて将来の平均気温を予測する方法を示しました。

また、統計的手法に基づき統計的に有意な予測因子を選択するために statsmodels ライブラリを使用する方法を説明した。

次に、この情報を利用して、Scikit-Learn の LinearRegression クラスを使用して、トレーニングサブセットから予測モデルを適合させました。

このフィットしたモデルを使って、テスト用のサブセットからの入力に基づいて期待値を予測し、予測の精度を評価したところ、妥当な精度を示すことができました。

この機械学習シリーズの最終回は、気温を予測するためのニューラルネットワークの構築方法について説明します。

タイトルとURLをコピーしました