派遣で働くエンジニアのスキルアップを応援するサイト

PRODUCED BY RECRUIT

特別編集 基礎から学ぶ、人工知能に必要な数学

f:id:itstaffing:20211215161928j:plain

人工知能(AI)や機械学習を根本から理解しようと学習すると、数学の知識が求められ、その難しさに頭を抱えてしまい挫折してしまう方も多いのではないでしょうか。実際、便利で手軽なフレームワークを使用すると、高い計算力がなくても大方困ることはありません。しかし、結果にエラーが起きてしまったときはどうでしょうか。数学は苦手だけどもう一歩踏み出して他人との差別化を図りたい方、ぜひご覧ください。基礎から学べるやさしい動画もご用意しています。

Pickup

1:【動画】人工知能(AI)向けの数学とPythonを基礎から学ぼう!

記事の内容
・文系の方やいつもフレームワークを使っている方におすすめ
・Pythonと数学を学び、機械学習の一種「ニューラルネットワーク」を学ぼう

2:【記事】人工知能(AI)、機械学習のための数学入門-Pythonのコードを書きながら学ぶ人工知能/深層学習に必要な数学

記事の内容
・どのように数学を機械学習で活用する?数式の攻略方法も解説
・ディープラーニングにおける行列の処理。ライブラリを使わずに実装する場合は?

3:【記事】数理最適化を理解して、機械学習の中身を知ろう

記事の内容
・機械学習アルゴリズムの仕組みを理解するために必要な数学
・「教師あり学習」を用いるパターン認識モデル「SVM」の考え方を知ろう

4:【漫画】ロジスティック回帰ってなあに?紹介編:未経験なのに、機械学習の仕事始めました

記事の内容
・機械学習の代表的な予測モデル「ロジスティック回帰」とは
・ロジスティック回帰を式ではどう表すの?

 

【第9話】ロジスティック回帰で、翌月の購買実績を予測してみよう!クロスバリデーション編【漫画】未経験なのに、機械学習の仕事始めました

f:id:itstaffing:20211129120554j:plain
f:id:itstaffing:20211129120605j:plain
f:id:itstaffing:20211129120612j:plain

クロスバリデーションとは?

前回は予測モデルを構築しました。しかし、モデルを作るのに利用したデータと、精度を計測するデータが同じになってしまうため、「予測がどのくらい正確にできているか」がわからないのが問題でした。

本番における精度がどの程度であるか、手元にあるデータだけで確認する方法を考えないといけません。

そこで役立つのが、クロスバリデーションという方法です!

・クロスバリデーション 3セットに分割した例

まず、全部で10レコードのデータを3分割に分けるとします。

*何セットに分割するかはデータ量や予測モデルの学習に必要な時間によって異なりますが、3、5、10分割のいずれかであることが多いです。ここでは3セットに分割したとして説明をします。

それぞれのグループは3レコード、3レコード、4レコードとなります。これらのセットにグループ1、グループ2,グループ3と名前をつけます。

次に、これらのグループの組み合わせを変えながら、モデルの学習と精度の計測をします。

・学習に使うデータを、学習データ(または訓練データ)
・計測に使うデータを、検証データ

と呼びます。
グループの組み合わせとしては、次のようになります。

f:id:itstaffing:20211129120619j:plain

このように、グループの組み合わせを3通り作成します。つまり、学習と精度計測を3回行います。3回の精度計測の平均を、予測モデルが持つ予測の精度として扱います。

組み合わせを変えながら学習と検証を実施できるので、全てのデータに対して学習と検証をすることができ、無駄なくデータを使うことができます。

f:id:itstaffing:20210113102524j:plain
なるほど!もともと1つだったデータを分けて、入れ替えて使うのか。こうすれば、問題だった「学習データ=検証データ」の状態にはならない。現実世界のデータで試しているような、本番っぽい状態を作れるってことね!

10セットのグループに分けた場合は、学習を10回することになるので、予測精度の計測に時間がかかってしまいますが、学習データに使えるデータ量が増えるという利点があります。

また、それぞれの予測精度のバラツキを確認するとモデルの安定性を知ることができます。極端に精度が異なる場合は、データの分割数を増やしたり、異なるモデルで予測したりする必要があるでしょう。

scikit-learnでクロスバリデーションを実装してみよう

scikit-learnでは以下のようにしてクロスバリデーションを実装できます。

特徴量Xと教師ラベルyを用意しました。この記事の実行を再現するために必要なサンプルコードは、こちらで確認できます。

```
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
model = LogisticRegression()
parameters = {} # デフォルトパラメータを利用
clf = GridSearchCV(model, parameters, cv=3, scoring="accuracy")
clf.fit(X, y)
```

結果の確認は`clf.cv_results_`で表示されて、以下のようになります。

```
{'mean_fit_time': array([0.01321475]),
'std_fit_time': array([0.00103848]),
'mean_score_time': array([0.0019633]),
'std_score_time': array([0.00012035]),
'params': [{}],
'split0_test_score': array([0.71849057]),
'split1_test_score': array([0.70415094]),
'split2_test_score': array([0.70015106]),
'mean_test_score': array([0.70759752]),
'std_test_score': array([0.00787374]),
'rank_test_score': array([1], dtype=int32)}
```

情報量が多いので最初は戸惑いますが、最初にみるべきはmean_test_scoreの値です。これが全組み合わせにおける予測精度の平均値になります。

ここでは0.707...となっています。十分な精度が出ている場合は、split0_test_score、 split1_test_score、split2_test_scoreの結果を見ます。

これらの数値が平均値を求める元になっています。ここでは大きなバラツキは無いようです。モデルやデータに問題がある場合はこれらの数値が大きくなります。

クロスバリデーションを実施する際に、予測モデルが持つパラメータを変えて比較することもできます。上記との違いはparametersのみです。

```
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
model = LogisticRegression()
parameters = {"penalty": ["l1", "l2"], "solver":["liblinear"]}
clf = GridSearchCV(model, parameters, cv=3, scoring="accuracy")
clf.fit(X, y)
```

クロスバリデーションの結果は、以下のようになります。

```
{'mean_fit_time': array([0.00588147, 0.00651034]),
'std_fit_time': array([0.00076274, 0.00138428]),
'mean_score_time': array([0.00222834, 0.00160066]),
'std_score_time': array([0.00013087, 0.00026224]),
'param_penalty': masked_array(data=['l1', 'l2'],
     mask=[False, False],
   fill_value='?',
     dtype=object),
'param_solver': masked_array(data=['liblinear', 'liblinear'],
     mask=[False, False],
   fill_value='?',
     dtype=object),
'params': [{'penalty': 'l1', 'solver': 'liblinear'},
{'penalty': 'l2', 'solver': 'liblinear'}],
'split0_test_score': array([0.73509434, 0.71698113]),
'split1_test_score': array([0.70339623, 0.70415094]),
'split2_test_score': array([0.72432024, 0.70015106]),
'mean_test_score': array([0.72093694, 0.70709438]),
'std_test_score': array([0.01315998, 0.00717917]),
'rank_test_score': array([1, 2], dtype=int32)}
```

先程との結果の違いはmean_test_scoreなどの値が2つになっていることです。パラメータの組み合わせごとにクロスバリデーションの結果が保存されています。また、最も精度の高いパラメータでのモデルはclf.predictで呼び出せます。

f:id:itstaffing:20210113102532j:plain
今回は、モデルの精度を検証するための方法「クロスバリデーション」を紹介しました。
クロスバリデーションは、複数のモデルを作ったうち、どれが最も優れているかを比較するときにも役立ちますよ
f:id:itstaffing:20210113102524j:plain
手持ちのデータが少ないときに、ありがたい方法ですね。モデルの精度はこれで検証できたから、もう完璧ですね!?
f:id:itstaffing:20210113102532j:plain
はい、精度についてはクロスバリデーションで検証できました。しかし、実はもうひとつ考えるべきポイントがあるんです。
f:id:itstaffing:20210113102524j:plain
あれ、まだ足りないんですか!?
f:id:itstaffing:20210113102532j:plain
予測結果をどちらに属するかの閾値(しきいち)です。
f:id:itstaffing:20210113102524j:plain
し、しきいち・・・
f:id:itstaffing:20210113102532j:plain
これまでは「予測結果が0.5以上か未満か」で区別していました。この閾値を最適なものに調整することで、モデルの実用性を増すことができます。次回は、調整における考え方を紹介します。
f:id:itstaffing:20210113102524j:plain
ヒョエ~!私は「ネットショッピングの利用者が翌月に購入するか否か」を予測したいだけなのに……考えることがいっぱいだ~!

第1話 機械学習の仕事内容って?実はコードを書くだけじゃない!
第2話 人工知能、機械学習、ディープラーニングの違いとは?
第3話 機械学習の活用事例!建設機械や回転寿司屋でも活用されている!?
第4話 機械学習したいのにデータがない!?
第5話 集計と可視化:pandasでデータの加工をしてみよう
第6話 続!集計と可視化:Plotlyでデータをグラフ化して傾向をとらえよう
第7話 ロジスティック回帰ってなあに?紹介編
第8話 ロジスティック回帰で、翌月の購買実績を予測してみよう!実践編

【筆者】
早川 敦士さん
株式会社FORCASの分析チームにてリーダーを務める傍らで、株式会社ホクソエムで執行役員として従事。新卒でリクルートコミュニケーションズに入社しWeb広告やマーケティングオートメーションなどのB2Cマーケティングを経験し、FORCASではB2Bマーケティングプラットフォームのデータ分析および開発を担当している。大学在学中に『データサイエンティスト養成読本』(技術評論社刊)を共著にて執筆。その後も『機械学習のための特徴量エンジニアリング』(オライリー・ジャパン刊)や『Pythonによるはじめての機械学習プログラミング』(技術評論社刊)などで執筆活動を続けている。国内最大級のR言語コミュニティであるJapan.Rを主催。Youtubeチャンネル『データサイエンティストgepuro』で動画を投稿。
・Twitterアカウント

湊川 あいさん
フリーランスのWebデザイナー・漫画家・イラストレーター。マンガと図解で、技術をわかりやすく伝えることが好き。 著書『わかばちゃんと学ぶ Git使い方入門』『わかばちゃんと学ぶ Googleアナリティクス』『わかばちゃんと学ぶ Webサイト制作の基本』『運用ちゃんと学ぶ システム運用の基本』『わかばちゃんと学ぶ サーバー監視』が発売中のほか、マンガでわかるGit・マンガでわかるDocker・マンガでわかるRuby・マンガでわかるScrapbox・マンガでわかるLINE Clova開発・マンガでわかる衛星データ活用といった分野横断的なコンテンツを展開している。
・Amazon著者ページ
・Twitterアカウント

わかばちゃんが登場する書籍いろいろ

イメージ イメージ
イメージ イメージ

わかばちゃんと学ぶシリーズ(Amazonページ)

 

特別編集 IT系の資格を取得するなら

f:id:itstaffing:20211108103827j:plain

IT系の資格は持っていますか?知識と技術を持っていることの証明となる資格ですが、実務にはあまり役立たないから、とそこまで重視していない方も多いのでは。そこで今回は、これまで資格取得について講義いただいたイベントレポートをまとめました。初心者の方が受けやすいものから国家資格まで。これ以外にもIT系の資格はさまざまあるので、ぜひ探してみてください。資格取得は、皆さんのスキルアップにもつながるはずです。

Pickup

1:CCNA改定前*の直前準備。ネットワークに必須のルーティング技術、NTP・DHCP・NATの設定についておさらいしよう!

記事の内容
・シスコ認定資格「CCNA」とは
・まずは、配点が高いシナリオ問題とシミュレーション問題を押さえよう

*2020年2月に試験内容が大幅に改定されました

2:時給を上げ、引く手数多のエンジニアになるために必要なことを知ろう

記事の内容
・国家資格「情報処理技術者試験」を取得するメリット
・これからのキャリア形成についても考えてみよう

3:Javaのスキルアップをしよう~Java SE 11 Silver認定試験ポイント解説~

記事の内容
・Oracle認定資格「JavaプログラマSE 11のSilver」とは
・出題傾向の具体的なポイントを解説

4:初心者歓迎!AWS認定ソリューションアーキテクトを目指すために

記事の内容
・AWS認定資格「AWS認定ソリューションアーキテクト」とは
・取得するためのノウハウや解答の考え方を解説

 

【第8話】ロジスティック回帰で、翌月の購買実績を予測してみよう!実践編【漫画】未経験なのに、機械学習の仕事始めました

f:id:itstaffing:20211020101914j:plain
f:id:itstaffing:20211020101917j:plain
f:id:itstaffing:20211020101919j:plain

★この記事で利用するサンプルコードは、こちらで確認できます。

モデル構築ライブラリ「scikit-learn」とは?

ロジスティック回帰の概要を第7話で紹介しました。ロジスティック回帰とは、簡単にいうと、データが与えられたときにAかBのどちらに属するのかを予測する方法です。

今回は、機械学習において最も有名なライブラリの一つである、scikit-learn(サイキット・ラーン)を用いて、ロジスティック回帰でモデルを構築します。

このライブラリはPythonから利用可能で、さまざまな機械学習手法を一貫したインタフェースで利用できます。つまり、一度ロジスティック回帰で予測モデルを構築する方法を学んだら、他の予測モデルも同じようにして作ることができるというメリットがあるのです。

▼ロジスティック回帰(LogisticRegression)以外にも、モデルを作るための他の機械学習手法が大量に用意されている

f:id:itstaffing:20211020101922j:plain

https://scikit-learn.org/stable/modules/classes.html#module-sklearn.linear_model

>> 拡大表示

f:id:itstaffing:20210113102529j:plain
ロジスティック回帰以外の手法でも、たくさん用意されている……だと…?自由度が高すぎて、使い方がむずかしそうなんですけど。
f:id:itstaffing:20210113102532j:plain
大丈夫!scikit-learnの使い方を紹介する技術書やブログって、とっても多いんです。つまずいてしまった場合も、役立つ記事や書籍に出会いやすいですよ。
f:id:itstaffing:20210113102524j:plain
よく使われているライブラリだから、本やブログで情報を集めやすいんだ!手順やサンプルコードが豊富に用意されているのは、初心者には助かるなぁ。
f:id:itstaffing:20210113102532j:plain
公式ドキュメントが充実していることも魅力の一つですね。

たとえばこちらのページでは、ロジスティック回帰を数式レベルから解説しています。このドキュメントの数式通りにライブラリが実装されているので、数式とコードの両面から手法を学べます。

f:id:itstaffing:20211020101924j:plain

https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression

>> 拡大表示

f:id:itstaffing:20210113102532j:plain
私個人の感想ですが、scikit-learnの実装は綺麗に書かれていると思うんですよね。 なので、Python自体の学習にも役立つと思います!
f:id:itstaffing:20210113102524j:plain
オープンソースで公開されてるんだ!個人、商用に関わらず、誰でも無料で使えるのはありがたいですね。

モデル構築ライブラリ「scikit-learn」を使ってみよう

f:id:itstaffing:20210113102532j:plain
それではさっそく、scikit-learn を使ってみましょう。次のようにコマンドを実行してくださいね。

・scikit-learn をインストールする

pip install scikit-learn

※Pythonの環境構築の手順は割愛します。

・ロジスティック回帰を利用する場合、次のようにしてクラスを読み込む

from sklearn.linear_model import LogisticRegression

・予測モデル構築の準備をする

model = LogisticRegression()

f:id:itstaffing:20210113102532j:plain
ロジスティック回帰をするには、sklearn.linear_model の中に LogisticRegressionモデルというのが用意されているので、上のコマンドのようにインポートして使うといいですよ。公式ドキュメントはこちらです。

さて、モデルを構築するための学習データは model.fix(X, y)で適用できます。

Xは特徴量と呼ばれるデータです。今回の例では、第6話で紹介したRFM分析の際に計算したデータを使います。

Recency(直近いつ)、Frequency(頻度)、Monetary(購入金額)を列に持ち、行方向にそれぞれの顧客が並んでいるデータです。

1番目の顧客のRFMは、 286, 0.002994, 77183.60
2番目の顧客のRFMは、 0, 0.017964, 4085.18

といったように、データが顧客数の数だけ並んでいるといった具合です。

yは翌月の購入実績の有無です。購入していた場合は True、購入していない場合はFalseとなる配列です。このデータについても、第6話で紹介したとおりです。

ロジスティック回帰で予測するには、次のように実行します。

・ロジスティック回帰で予測する

from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X, y)
model.predict(X)

最後のmodel.predict(X)を実行すると、予測結果を得られます。

それぞれの顧客に対して、翌月に購入すると予測した場合はTrue、購入しないと予測した場合はFalse が返ってきます。モデルの予測精度を確認する方法の一つとして分割表があります。実績値と予測値の集計で、それぞれの項目に名前がついています。

f:id:itstaffing:20211020101931j:plain

新型コロナウイルスの PCR 検査に関連して、偽陽性(False Positive、略して FP)という言葉を聞いたことがあるかもしれません。感染していないにもかかわらず、検査結果が陽性と判定されてしまうケースです。機械学習においても偽陽性が発生します。翌月に購入しないにもかかわらず、購入すると予測してしまったケースです。予測通りに顧客が商品を購入した場合真陽性(True Positive、略して TP)、逆に予想通りに購入しなかった場合は真陰性(True Negative、略して TN)と言います。

Pandasで分割表を計算する場合はcrosstabを利用します。

  pd.crosstab(
    y,
    model.predict(X),
    rownames=["購入実績"],
    colnames=["予測結果"],
  )

f:id:itstaffing:20211020101933j:plain

全件に対して予測が的中した割合を正解率(Accuracy)と呼びます。これは、予測モデルの精度を比較する指標のひとつとして有名です。正解率は、(TN+TP)/(TN+FP+FN+TP) で計算します。今回のケースでは、正解率は(2515+287)/(2515+118+1054+287)≒0.705 となります。

f:id:itstaffing:20211020101927j:plain

次回は、予測モデルの精度を計算する方法であるクロスバリデーションを紹介します。お楽しみに!

第1話 機械学習の仕事内容って?実はコードを書くだけじゃない!
第2話 人工知能、機械学習、ディープラーニングの違いとは?
第3話 機械学習の活用事例!建設機械や回転寿司屋でも活用されている!?
第4話 機械学習したいのにデータがない!?
第5話 集計と可視化:pandasでデータの加工をしてみよう
第6話 続!集計と可視化:Plotlyでデータをグラフ化して傾向をとらえよう
第7話 ロジスティック回帰ってなあに?紹介編

【筆者】
早川 敦士さん
株式会社FORCASの分析チームにてリーダーを務める傍らで、株式会社ホクソエムで執行役員として従事。新卒でリクルートコミュニケーションズに入社しWeb広告やマーケティングオートメーションなどのB2Cマーケティングを経験し、FORCASではB2Bマーケティングプラットフォームのデータ分析および開発を担当している。大学在学中に『データサイエンティスト養成読本』(技術評論社刊)を共著にて執筆。その後も『機械学習のための特徴量エンジニアリング』(オライリー・ジャパン刊)や『Pythonによるはじめての機械学習プログラミング』(技術評論社刊)などで執筆活動を続けている。国内最大級のR言語コミュニティであるJapan.Rを主催。Youtubeチャンネル『データサイエンティストgepuro』で動画を投稿。
・Twitterアカウント

湊川 あいさん
フリーランスのWebデザイナー・漫画家・イラストレーター。マンガと図解で、技術をわかりやすく伝えることが好き。 著書『わかばちゃんと学ぶ Git使い方入門』『わかばちゃんと学ぶ Googleアナリティクス』『わかばちゃんと学ぶ Webサイト制作の基本』『運用ちゃんと学ぶ システム運用の基本』『わかばちゃんと学ぶ サーバー監視』が発売中のほか、マンガでわかるGit・マンガでわかるDocker・マンガでわかるRuby・マンガでわかるScrapbox・マンガでわかるLINE Clova開発・マンガでわかる衛星データ活用といった分野横断的なコンテンツを展開している。
・Amazon著者ページ
・Twitterアカウント

わかばちゃんが登場する書籍いろいろ

イメージ イメージ
イメージ イメージ

わかばちゃんと学ぶシリーズ(Amazonページ)

 

第6話 ExcelからAccessの読み書き【連載】実務で使えるAccessのコツ

f:id:itstaffing:20210924112110j:plain

データベース管理ソフトウェア、Accessを実務で使うときに「知っているとちょっと便利なコツ」について紹介するこのコラム。今回は、Excelと連携させることの最大のメリットをご紹介します。あわせて知っておきたい、悪意のある第三者にどう対応するかのセキュリティ面についても解説。最終回となる今回のお話しも、あなたのAccess力アップに役立ちますように。

前回のコラムを見逃した方はこちらからご覧ください。
第5話 VBA内でSQLを扱うコツ

【筆者】今村 ゆうこさん
【筆者】今村 ゆうこさん
地方の非IT系企業に勤務し、業務アプリケーション開発を行うプログラマー。著書のイラストや図解も手掛けている。大学卒業後出身地へUターン就職し、2度の産休/育休を経て現在は小学生と保育園児の2人のこどもを抱えるワーキングマザー。主にVBAを使ってデータベースの情報を加工/展開するアプリを開発するほか、WordPressを使った個人ブログ(https://ateitexe.com/)で技術情報を発信している。著書に『Accessデータベース 本格作成入門』『Excel & Access連携 実践ガイド』(技術評論社)など。

ExcelとAccessを連携させると…?

Excelの次のステップアップとしてAccessにチャレンジしてみよう、という気持ちで始める方も多いことと思います。データベースの構造を知ることで効率の良いデータの管理方法がわかり、結果的にExcelを活用する力も向上するはずです。

しかし、AccessはExcelの上位互換というわけではありません。Excelはグラフ化や視覚的な分析が得意ですが、入力の自由度が高すぎるためにデータを整然と保つのが苦手です。対してAccessはデータ管理のスペシャリストですが、Excelほどに自由度の高いUIやグラフ化は苦手なのです。

f:id:itstaffing:20210924112202j:plain

最終回である今回は、そんなお互いの苦手な部分を補完し合うと便利な例をご紹介いたします。

Excelにデータを持たなくていい

連携させることの最大のメリットは、Excelでデータの管理をしなくてもよくなることです。管理はAccessにまかせて、Excel側では必要なときに必要なデータだけ取り出して表やグラフに活用すれば、お互いのソフトの「いいとこ取り」でスマートに使うことができます。

Accessが苦手なユーザーにも受け入れられやすい

Microsoft Officeシリーズの仲間とはいえ、一般ユーザーからするとAccessの認知度は高くありません。慣れ親しんだExcelのシートだと心理的な抵抗感が少ないユーザーも多くいらっしゃるので、UI部分をExcelで作るのも、ユーザーの「使いやすい」と感じる1つの要素になり得ます。

読み込み即グラフ化が可能

たとえば以下のようなExcelシートがあるとします。上部のグラフは下部の表に紐付いており、表に数値が入ると棒グラフが描写される設定になっています。

f:id:itstaffing:20210924112217j:plain

このシートのB2セル(年)を変更してマクロを実行すれば、その年に応じたデータが読み込まれてグラフが描写される、なんて素敵だと思いませんか?そんなことが可能なんです。

読み書きのテンプレート

それでは、Accessのテーブルから読み書きするためのテンプレートを任意のExcelファイル(.xlsm)のVBEに書いていきます。

今回は参照設定の「Microsoft ActiveX Data Objects X.X Library」にチェックを入れずにADOを利用するコードでご紹介します。詳しくは第4回の記事も合わせてご覧ください。

以下はExcelからAccessのファイルを指定して接続したり、接続解除したりする部分を切り出してプロシージャ化したものです。何度も使われる部分になるので、こうして部品化しておくと取り回しが楽になります。

上の3行がモジュールの先頭(宣言セクション)に書かれるように、新しい標準モジュールにコピー&ペーストし、Accessのパスは任意のものへ変更してください。

Private cn As Object  'ADOコネクション用オブジェクトの宣言
Private Const adStateOpen = 1  'レコードセットが開いている場合の設定値
Private Const adOpenKeyset = 1  'レコードセットカーソルタイプの設定値

Private Sub connectDB()
  '## 接続

  Set cn = CreateObject("ADODB.Connection") 'ADOコネクションを作成
  cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
      "Data Source=C:\data.accdb;"  'Accessファイルを指定してコネクションを開く
End Sub

Private Sub disconnectDB()
  '## 接続解除

  If Not cn Is Nothing Then
    cn.Close
    Set cn = Nothing
  End If
End Sub

以下はレコードの抽出で使用するテンプレートです。引数のSQLによってAccessから抽出されたレコードを、Excelの指定シート・セル起点で展開します。上の接続/接続解除のプロシージャと同じモジュールに書いてください。

Public Sub putRsOnSheet(ByVal sql As String, ByVal ws As Worksheet, ByVal rng As Range)
  '## レコードセットをシートへ展開

  On Error GoTo Err_Handler  'エラーが起きたら「ErrorHandler」にジャンプする指示

  Call connectDB  '接続

  'レコードセットのオープン
  Dim rs As Object  'レコードセット用変数宣言
  Set rs = CreateObject("ADODB.RecordSet")  'ADOレコードセットオブジェクトを作成
  rs.Open sql, cn  'レコードセットを開く

  '空だったら最終処理へ
  If rs Is Nothing Or (rs.BOF And rs.EOF) Then  'レコードセットやレコードが存在しなかった場合
    MsgBox "対象レコードがありません", vbInformation, "確認"  'メッセージ出力
    GoTo Finally  '最終処理へジャンプ
  End If

  'シートに展開
  Dim tgtRow As Long
  tgtRow = rng.Row  'スタートの行
  Dim tgtCol As Long
  tgtCol = rng.Column  'スタートの列
  Application.ScreenUpdating = False  '画面更新OFF
  Do Until rs.EOF  'レコードセットが終了するまで処理を繰り返す
    Dim fldNum As Long  'フィールドの繰り返し用変数
    For fldNum = 0 To rs.Fields.Count - 1  'フィールドの数だけ繰り返す
      ws.Cells(tgtRow, tgtCol + fldNum).Value = rs(fldNum)  'フィールドの並び順でセルに書き込む
    Next fldNum  '次のフィールドへ
    tgtRow = tgtRow + 1  '行をカウントアップする
    rs.MoveNext  '次のレコードに移動する
  Loop
  Application.ScreenUpdating = True  '画面更新ON

  GoTo Finally  '正常に終了したら最終処理へジャンプ

Err_Handler:  '例外処理
  Dim msgTxt As String
  msgTxt = "Error #: " & Err.Number & vbNewLine & vbNewLine & Err.Description  'エラーメッセージが入る
  MsgBox msgTxt, vbOKOnly + vbCritical, "エラー"  'メッセージ出力

Finally:  '最終処理
  If Not rs Is Nothing Then  'レコードセットオブジェクトが存在している場合のみ
    If rs.State = adStateOpen Then rs.Close  'レコードセットが開いていたら閉じる
    Set rs = Nothing
  End If

  Call disconnectDB  '接続解除
End Sub

以下はレコードの挿入・更新・削除で使用するテンプレートです。引数のコレクション内に格納されているすべてのSQLを実行します。上の接続/接続解除のプロシージャと同じモジュールに書いてください。

Public Function tryExecute(ByVal sqlList As Collection) As Boolean
  '## SQLの実行

  On Error GoTo ErrorHandler  'エラーが起きたら「ErrorHandler」にジャンプする指示

  Call connectDB  '接続

  cn.BeginTrans  'トランザクション開始

  '実行
  Dim sql As Variant
  For Each sql In sqlList  'SQL文リストをループ
    cn.Execute sql  '1行ずつ実行
  Next sql

  cn.CommitTrans  '確定

  tryExecute = True  '成功だった場合、関数の結果にTrueを入れる
  GoTo Finally  '正常に終了したら最終処理へジャンプ

ErrorHandler:  '例外処理
  cn.RollbackTrans  '元の状態へ戻す
  Dim msgTxt As String
  msgTxt = "Error #: " & Err.Number & vbNewLine & vbNewLine & Err.Description  'エラーメッセージが入る
  MsgBox msgTxt, vbOKOnly + vbCritical, "エラー"  'メッセージ出力

Finally:  '最終処理
  Call disconnectDB  '接続解除
End Function

テンプレートの利用(レコードをExcelシートに展開)

SQLのSELECT構文を作成し、起点とするシート・セルと共に引数としてテンプレートへ渡すコードがこちらです。

Public Sub loadRecord()
  '## レコードをシートへ

  '対象シートを設定
  Dim ws As Worksheet
  Set ws = Sheets("シート名")

  'SQL文の作成
  Dim sql As String
  sql = "任意のSELECT文"

  'レコードセットをシートへ展開
  Call putRsOnSheet(sql, ws, ws.Range("A1"))
End Sub

実行すると、指定のセルを起点にレコードセットが展開されます。

さきほど例に出した、グラフが設定されているシートに展開するコードだったら、以下のように書きます。SQLではPIVOTを使ったクロス集計を行っています。

(接続するAccessファイルに「販売」テーブルが存在し、その中に「商品ID(文字列型)」「売上日(日付型)」「数量(数値型)」フィールドがある想定です)

Public Sub loadRecord()
  '## レコードをシートへ

  '対象シートを設定
  Dim ws As Worksheet
  Set ws = Sheets("集計")

  '指定年取得
  Dim tgtYear As Long
  tgtYear = ws.Range("B2").Value

  'SQL文の作成
  Dim sql As String
  sql = _
    "TRANSFORM Sum(数量) " & _
    "SELECT 商品ID " & _
    "FROM 販売 " & _
    "WHERE Format(売上日,'yyyy') In ('" & tgtYear & "')" & _
    "GROUP BY 商品ID " & _
    "PIVOT Format(売上日,'m') In ('1','2','3','4','5','6','7','8','9','10','11','12');"

  'レコードセットをシートへ展開
  Call putRsOnSheet(sql, ws, ws.Range("B16"))
End Sub

実行すると以下のようにデータが展開され、自動的にグラフが描写されます。

f:id:itstaffing:20210924112223j:plain

B2セルの値を変更してプログラムを実行し直すことで、その年のデータを月別に読み込むことができます。SQLを工夫すれば、年月を指定して日別のグラフにすることも可能です。

テンプレートの利用(レコードの挿入・更新・削除)

SQLのINSERT/UPDATE/DELETE構文をコレクションに格納し、引数としてテンプレートへ渡して結果をTrue/Falseの形で受け取るコードがこちらです。

Public Sub executeSQL()
  '## レコードの挿入・更新・削除

  'コレクションの作成
  Dim sqlList As Collection
  Set sqlList = New Collection

  'SQL作成
  Dim sql As String 'SQL文用変数の宣言

  sql = "任意のINSERT/UPDATE/DELETE構文"  '1つ目のSQL文
  sqlList.Add sql  'コレクションへ追加

  sql = "任意のINSERT/UPDATE/DELETE構文"  '2つ目のSQL文
  sqlList.Add sql  'コレクションへ追加

  '実行
  If tryExecute(sqlList) Then  '処理が成功した場合
    MsgBox "正常に終了しました", vbOKOnly + vbInformation, "終了"  '終了メッセージ
  End If
End Sub

実行すると、問題が起きた場合は処理されずにエラー内容が、問題なく処理が終了した場合は終了メッセージが表示されます。

f:id:itstaffing:20210924112230j:plain

SQLにExcel上のセルの値を組み込めば、自由度の高いシステムを作ることができます。

VBAでプレースホルダーを使う

ユーザーが入力した値をそのままSQLに組み込んでデータベースを操作する場合、さらにその入力する人間にSQL知識と悪意がある場合は、SQLインジェクション(不正なSQL文を実行させる攻撃)の恐れがあることに注意をしなければなりません。

Accessは個人~少人数向けの非公開が前提のデータベースソフトなので悪意のある第三者が介入する可能性は低いと思われますが、知識として知っておくことは大切です。

この問題に対しては、入力値を一旦別の場所に確保(プレースホルダー)しておいて、実行のときに無害化して使うのが一般的な手段で、VBAでも実装が可能です。

それでは最後に、VBAでプレースホルダーを使った書き方も見ておきましょう。

以下はレコードの抽出で使用するテンプレートです。レコードセットを取得してイミディエイトウィンドウへ出力する動きを、1つのプロシージャで完結する形で書いてあります。SQL条件の値に「?」を置き、プレースホルダーの値を配列型でパラメーターとして持たせます。

Public Sub loadRecord ()
  '接続
  Dim cn As Object  'ADOコネクション用オブジェクト
  Set cn = CreateObject("ADODB.Connection")
  cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
        "Data Source=C:\Data.accdb;"  'Accessファイルを指定してコネクションを開く

  'ADOコマンドオブジェクトの設定
  Dim cmd As Object
  Set cmd = CreateObject("ADODB.Command")
  cmd.ActiveConnection = cn

  'ADOレコードセットオブジェクトの設定
  Dim rs As Object
  Set rs = CreateObject("ADODB.RecordSet")

  '実行
  cmd.CommandText = "SELECT * FROM table1 WHERE f1 = ? ;"
  Set rs = cmd.Execute(Parameters:=Array("a"))

  Do Until rs.EOF  'レコードセットが終了するまで処理を繰り返す
    Dim fldNum As Long  'フィールドの繰り返し用変数
    For fldNum = 0 To rs.Fields.count - 1  'フィールドの数だけ繰り返す
        Debug.Print rs(fldNum), ;  'フィールドを改行せずイミディエイトウィンドウに出力
    Next fldNum  '次のフィールドへ
    Debug.Print ""  'レコード切り替えでイミディエイトウィンドウを改行
    rs.MoveNext  '次のレコードに移動する
  Loop

  'レコードセットオブジェクトの処理
  rs.Close  'レコードセットを閉じる
  Set rs = Nothing

  'コマンドオブジェクトの後処理
  Set cmd = Nothing

  '接続解除
  cn.Close
  Set cn = Nothing
End Sub

以下はレコードの挿入・更新・削除で使用するテンプレートです。1つのプロシージャで完結する形で書いてあります。「?」を複数使用する場合は、パラメーターの配列に順番に配置します。

Public Sub executeSQL()
  '接続
  Dim cn As Object  'ADOコネクション用オブジェクト
  Set cn = CreateObject("ADODB.Connection")
  cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
        "Data Source=C:\Data.accdb;"  'Accessファイルを指定してコネクションを開く

  'ADOコマンドオブジェクトの設定
  Dim cmd As Object
  Set cmd = CreateObject("ADODB.Command")
  cmd.ActiveConnection = cn

  '実行
  cmd.CommandText = "INSERT INTO table1(f1, f2, f3, f4) VALUES(?, ?, ?, ?);"
  cmd.Execute Parameters:=Array(1, Now, "a", False)

  'コマンドオブジェクトの後処理
  Set cmd = Nothing

  '接続解除
  cn.Close
  Set cn = Nothing
End Sub

Excelからデータベースを操作できると、仕事の可能性がぐんと広がります。対象のデータベースの規模が大きくなれば気をつけなくてはならないことも増えるので、セキュリティ面も勉強しながらステップアップを目指してくださいね。

以上で、連載「実務で使えるAccessのコツ」は終了です。この連載が、あなたのお仕事に役に立てたらとっても嬉しいです。ここまで読んでいただき、ありがとうございました!

第1話「イベント」を使いこなそう
第2話 レイアウトで躓きやすいポイント
第3話 マクロとVBAの違い
第4話 DAOとADOの違い
第5話 VBA内でSQLを扱うコツ

 

第5話 VBA内でSQLを扱うコツ【連載】実務で使えるAccessのコツ

f:id:itstaffing:20210827161938j:plain

データベース管理ソフトウェア、Accessを実務で使うときに「知っているとちょっと便利なコツ」について紹介するこのコラム。今回は、VBA内に複雑なSQLを組み込むための手順を解説します。複雑なものほど長くなるSQLですが、なにを使って区切ると読みやすくなるのでしょうか。あなたのAccess力アップに役立ちますように。

前回のコラムを見逃した方はこちらからご覧ください。
第4話 DAOとADOの違い

【筆者】今村 ゆうこさん
【筆者】今村 ゆうこさん
地方の非IT系企業に勤務し、業務アプリケーション開発を行うプログラマー。著書のイラストや図解も手掛けている。大学卒業後出身地へUターン就職し、2度の産休/育休を経て現在は小学生と保育園児の2人のこどもを抱えるワーキングマザー。主にVBAを使ってデータベースの情報を加工/展開するアプリを開発するほか、WordPressを使った個人ブログ(https://ateitexe.com/)で技術情報を発信している。著書に『Accessデータベース 本格作成入門』『Excel & Access連携 実践ガイド』(技術評論社)など。

業務で使えるSQLを作るには

前回の記事では、AccessVBAでSQLを「処理する部分」のテンプレートの書き方をご紹介しました。このテンプレートがあれば、SQLだけ書き換えれば自由度の高い使い方ができてとっても便利です。

ただ、この「SQLを書き換えるだけ!」が意外と難しくて、固定値の短いSQL文ならばそれほどではありませんが、業務で使うとなるとどうしても複雑になりがちです。

そういったSQL文は細かいパズルのようで、うっかり必要な記述が抜けてしまったり、そのミスに気づきにくかったり、慣れるまではゴールが遠く感じてしまうかもしれません。

f:id:itstaffing:20210827161940j:plain

今回は、そんなSQLパズルの組み立て方のコツをご紹介します。

SQLの基本形をおさらい

まずはSQLでレコード操作するための基本の文を見てみましょう。

・抽出 → SELECT フィールド1, フィールド2 FROM テーブル WHERE 条件;
・挿入 → INSERT INTO テーブル(フィールド1, フィールド2) VALUES(値1, 値2);
・更新 → UPDATE テーブル SET フィールド1=値1, フィールド2=値2 WHERE 条件;
・削除 → DELETE FROM テーブル WHERE 条件;

使うときに大切なのは、フィールドのデータ型です。値はデータ型に適した形で書かなければなりません。

上のINSERT文を例にすると、たとえばフィールド1が数値型でフィールド2がブーリアン型の場合、対応する値は以下のように書きます。*真(true)か偽(false)のどちらかの値が入る

f:id:itstaffing:20210827161943j:plain

フィールド1が文字列型だった場合は「'」を、フィールド2が日付型だった場合「#」を、対応する値にそれぞれ付けることでデータ型に対応させます。

f:id:itstaffing:20210827161947j:plain

この識別記号の扱いをよく覚えておきましょう。

VBA内ではSQLは“文字列”で扱う

VBA内ではSQLはそのまま認識できないので、文字列として扱うことになります。前回の記事で紹介したテンプレートを使う側では、レコードを抽出するコード(抜粋)は以下で、

Public Sub selectRecord()
  '## レコードの抽出

  'SQL作成
  Dim sql As String
  sql = "任意のSELECT構文"

  '以下略
End Sub

レコードを挿入・更新・削除するコード(抜粋)は以下のようになっていましたよね。

Public Sub executeSQL()
  '## レコードの挿入・更新・削除

  'コレクションの作成
  Dim sqlList As Collection
  Set sqlList = New Collection

  'SQL作成
  Dim sql As String 'SQL文用変数の宣言

  sql = "任意のINSERT/UPDATE/DELETE構文"
  sqlList.Add sql 'コレクションへ追加

  '以下略
End Sub

このように、VBA内でのSQLは、「"」で括ることで、文字列として扱います。SQLの文字列は「'」、VBAの文字列は「"」と、使い分けておきましょう。

さきほど例に挙げた、データ型の識別記号を含めたINSERT文をVBA内に書くならば、以下のようになるわけです。

f:id:itstaffing:20210827161916j:plain

ここまで、しっかり理解しておきましょう。

VBA内に複雑なSQLを組み込むための手順

それではもう少し具体的に、VBA内で変数を組み込んだSQL文を作成してみます。

以下は「販売」テーブル内の「ID」フィールド(文字列型)、「売上日」フィールド(日付型)へ値を挿入するSQLです。

f:id:itstaffing:20210827161920j:plain

1.まずは1行の文字列にする

f:id:itstaffing:20210827161923j:plain

はじめに、「"」で括っただけの1つの文字列でレコード操作ができるか確認してください。このとき、適切な場所に「半角スペース」が含まれているかが大切です。必要なスペースが入っていないと、この時点でエラーになってしまいます。

2.句の区切りで分割する

f:id:itstaffing:20210827161929j:plain

複雑なSQLは長くなるので、VALUES、WHEREなどの区切りで分割すると読みやすくなります。「"」で括られている文字列が2つになり、文字列同士を「&」で結合しています。

<p">このとき、「VALUES」直前のスペースを忘れないように気をつけてください。スペースをどちらの文字列に含むかは好みですが、統一しておくとよいでしょう(筆者はスペースを文字列の最後に含めるようにしています)。

3.改行する

f:id:itstaffing:20210827161926j:plain

VBE(Visual Basic Editor)内で、改行は「 _」(半角スペース+アンダースコア)です。2つに分割した文字列を改行して、インデントを入れて行頭を揃えましょう。

この改行はVBA上のもので、文字列合成されたSQL文内には改行は含まれません。

4.フィールドごとに分割&改行する

f:id:itstaffing:20210827161932j:plain

フィールドがたくさんある場合は、フィールドと値を1つの要素ずつ改行しておくと比較的読みやすくなります。このとき、インデントを入れておくとさらに良いでしょう。最終的にSQLが正しく認識されれば動作するので、あまり細かく分割されすぎないほうがよい方は適宜で構いません。

5.可変部分を分割する

f:id:itstaffing:20210827161935j:plain

「P001」や「2021/1/1」は、実務では変数を使いたい部分です。「'」や「#」などの識別子を分割して、可変部分のみ切り出します。

6.変数に置き換える

f:id:itstaffing:20210827161935j:plain

可変部分を変数に置き換えます。変数部分は、Form.Textbox.Valueのように書けば、フォーム上のテキストボックスの値を組み込むこともできます。

以上の手順はあくまで一例ですので、ご自身の理解しやすい形にしていただければと思います。

なお、Accessはインハウスデータベース(企業などが自社で利用するための情報を非公開で蓄積するデータベース)の中でも非常に少人数かつ限定的に使われるものなので、SQLインジェクション(不正なSQL文を実行させる攻撃)の可能性は低いと思われますが、VBAでも対策は可能です。こちらは次回記事でご紹介いたします。

例)テーブル結合があるSELECT文

それでは次は、よく登場する複数テーブルからのSELECT文を見てみましょう。一文で書くと以下のように長くて、読み解くのがつらいですね。しかし、この時点でちゃんと動くかどうか確認しておきましょう。ここに問題があった場合、後で原因をたどるのが困難になってしまいます。

sql = "SELECT T1.販売ID, T1.商品ID, T2.商品名, T1.売上日, T1.数量, T2.定価 FROM 販売データ AS T1 INNER JOIN 商品マスター AS T2 ON T1.商品ID = T2.商品ID WHERE T1.売上日 BETWEEN #2021/01/01# AND #2021/01/30# ORDER BY T1.売上日 DESC;"

まずは大きな区切り(上記で色が付いている部分)で文字列を分割・改行します。インデントで行頭を揃えるのも忘れずに。これだけでもかなり読みやすくなりましたね。

sql = _
  "SELECT T1.販売ID, T1.商品ID, T2.商品名, T1.売上日, T1.数量, T2.定価 " & _
  "FROM 販売データ AS T1 INNER JOIN 商品マスター AS T2 ON T1.商品ID = T2.商品ID " & _
  "WHERE T1.売上日 BETWEEN #2021/01/01# AND #2021/01/30# " & _
  "ORDER BY T1.売上日 DESC;"

FROM句がまだ情報量が多いので改行してみましょう。関連項目はさらに一段インデントを入れておくとわかりやすくなります。

sql = _
  "SELECT T1.販売ID, T1.商品ID, T2.商品名, T1.売上日, T1.数量, T2.定価 " & _
  "FROM 販売データ AS T1 " & _
    "INNER JOIN 商品マスター AS T2 " & _
    "ON T1.商品ID = T2.商品ID " & _
  "WHERE T1.売上日 BETWEEN #2021/01/01# AND #2021/01/30# " & _
  "ORDER BY T1.売上日 DESC;"

現時点ではWHERE句の条件は1つだけですが、複数設定する場合は、条件ごとに改行してインデントを入れると可読性が良くなります。

sql = _
  "SELECT T1.販売ID, T1.商品ID, T2.商品名, T1.売上日, T1.数量, T2.定価 " & _
  "FROM 販売データ AS T1 " & _
    "INNER JOIN 商品マスター AS T2 " & _
    "ON T1.商品ID = T2.商品ID " & _
  "WHERE " & _
    "T1.売上日 BETWEEN #2021/01/01# AND #2021/01/30# " & _
    "AND T1.商品ID = 'P001' " & _
  "ORDER BY T1.売上日 DESC;"

フィールドの改行はお好みですが、改行する場合はインデントを入れると良いでしょう。

sql = _
  "SELECT " & _
    "T1.販売ID, " & _
    "T1.商品ID, " & _
    "T2.商品名, " & _
    "T1.売上日, " & _
    "T1.数量, " & _
    "T2.定価 " & _
  "FROM 販売データ AS T1 " & _
    "INNER JOIN 商品マスター AS T2 " & _
    "ON T1.商品ID = T2.商品ID " & _
  "WHERE " & _
    "T1.売上日 BETWEEN #2021/01/01# AND #2021/01/30# " & _
    "AND T1.商品ID = 'P001' " & _
  "ORDER BY T1.売上日 DESC;"

WHERE句の条件値を変数に置き換えます。こうしておけば、柔軟に条件を変えて抽出することができます。「'」や「#」の識別子の有無に注意しながら記述しましょう。

sql = _
  "SELECT " & _
    "T1.販売ID, " & _
    "T1.商品ID, " & _
    "T2.商品名, " & _
    "T1.売上日, " & _
    "T1.数量, " & _
    "T2.定価 " & _
  "FROM 販売データ AS T1 " & _
    "INNER JOIN 商品マスター AS T2 " & _
    "ON T1.商品ID = T2.商品ID " & _
  "WHERE " & _
    "T1.売上日 BETWEEN #" & date1 & "# AND #" & date2 & "# " & _
    "AND T1.商品ID = '" & id & "' " & _
  "ORDER BY T1.売上日 DESC;"

なお、文字列の改行が多くなりすぎると認識されなくなってしまうので、長くなる場合はいったん終わらせて、改めて今まで書いた文字列と結合するという方法もあります。

sql = _
  "SELECT " & _
    "T1.販売ID, " & _
    "T1.商品ID, " & _
    "T2.商品名, " & _
    "T1.売上日, " & _
    "T1.数量, " & _
    "T2.定価 "

sql = sql & _
  "FROM 販売データ AS T1 " & _
    "INNER JOIN 商品マスター AS T2 " & _
    "ON T1.商品ID = T2.商品ID " & _
  "WHERE " & _
    "T1.売上日 BETWEEN #" & date1 & "# AND #" & date2 & "# " & _
    "AND T1.商品ID = '" & id & "' " & _
  "ORDER BY T1.売上日 DESC;"

イミディエイトウィンドウに出力して間違いを探す

SQLの記述は、1つ手を加えたらその都度動作確認をしていく癖をつけておくと、「どこで間違いが発生しているのかわからない!」という状況にハマりにくくなります。

しかしながら、ループ内で変数が意図しない値になるなど、不測の事態はいつでも起こり得ます。原因を調査するときは、合成した後のSQLがどんな形になっているかをイミディエイトウィンドウに出力してみると間違いが見つけやすくなります。

Dim sql As String
sql = "任意のSQL文"

Debug.Print sql

いかがだったでしょうか? 最初はちょっととっつきにくいと思いますが、変数を組み込んだSQLが扱えるようになるとできることがグッと広がります。ぜひチャレンジしてみてください!

さて、次回でこのコラムは最終回です。最後にExcelからAccessのデータベースを読み書きする方法をご紹介いたします。ご期待ください。

第1話「イベント」を使いこなそう
第2話 レイアウトで躓きやすいポイント
第3話 マクロとVBAの違い
第4話 DAOとADOの違い

リクルートスタッフィング

【第7話】ロジスティック回帰ってなあに?紹介編【漫画】未経験なのに、機械学習の仕事始めました

f:id:itstaffing:20210810141902j:plain
f:id:itstaffing:20210810141905j:plain
f:id:itstaffing:20210810141909j:plain
f:id:itstaffing:20210810141912j:plain
f:id:itstaffing:20210113102532j:plain
第5話第6話では、データの集計と可視化を実践しましたね!今回から、 いよいよ機械学習に入っていきましょう!

  未知の事象を予測する! ロジスティック回帰ってなあに?    

いよいよ機械学習について学んでいきましょう。機械学習には多種多様な手法がありますが、代表的な予測モデルの1つであるロジスティック回帰を紹介します。

ロジスティック回帰は、パターンAやパターンBのように2パターンに分けることができる事象に対して、AかBのどちらに属するかを予測できる手法です。

・雨が降るか否か
・試験に合格するか否か
・商品を購入するか否か
・犬か猫か

といったように、2パターンのどちらかに該当するかを予測します。

たとえば、過去に受験した模擬試験の結果を使うことで「本番の試験に合格するか否か」を予測できるかもしれません。

予測をするために利用するデータのことを、説明変数と言います。

複数の説明変数を使うことができ、国語の点数、数学の点数、社会の点数のように具体的な数字が入ります。また、「公立校に在籍している」「私立校に在籍している」という定性的なカテゴリーデータも説明変数に加えられます。

一方で、予測対象のデータもロジスティック回帰には必要で、これを目的変数と呼びます。

具体的には、

・試験に合格した場合は1
・不合格の場合は0

のように表現します。

予測に使う説明変数、予測対象の目的変数の2つを用いて、ロジスティック回帰という手法でデータの傾向を捉えます。このように傾向を捉えるのに利用するデータを訓練データ(または学習データ)と呼びます。

訓練データで傾向を捉えることができたら、試験をまだ受けていない生徒に対しても、模擬試験の結果から合否を予測できます。このとき、試験を受けてない生徒の予測に使うデータは、訓練データにおける説明変数と同じ項目です。

f:id:itstaffing:20210113102524j:plain
説明変数、目的変数、訓練データ……?次々に新しい単語が出てきて、混乱してきました。
f:id:itstaffing:20210113102532j:plain
ではここで一度、整理しておきましょう。

説明変数・・・予測をするために利用するデータのこと
例:国語の点数、数学の点数、社会の点数、公立校/私立高校在籍など、複数を活用することができる

目的変数・・・予測対象のデータのこと
例:試験に合格した場合は1、不合格の場合は0

訓練データ・・・傾向を捉えるのに利用するデータのこと
(ここでは、説明変数、目的変数のこと)

  ロジスティック回帰は、確率で予測できる!    

ロジスティック回帰では、予測結果を確率として考えることができます。「合格率70%です」「合格率20%です」というように、具体的な数値を得ることができるということです。

予測結果に対して、

・閾値を超えたら合格
・閾値未満であれば不合格

というように予測します。 (*区切りの基準になる値のこと)

単純に50%を超えたら合格と判定することもできますが、予測間違いに対する許容度で閾値を設定することもできます。

「予測で合格判定したにも関わらず、実際には不合格になってしまう生徒」を減らしたい場合は、閾値を70%のように高めに設定することで防げます。

f:id:itstaffing:20210113102532j:plain
ちなみに、機械学習ライブラリでは、パーセント表示ではなく0.7や0.2 のように小数点で結果を得るのが一般的です。

  ロジスティック回帰をもっと詳しく知りたい!    

では、ロジスティック回帰の詳細に踏み込んでいきます。

f:id:itstaffing:20210810141915j:plain

という式で表せます。

f(x)は出力結果で、0.7や0.2のように予測した合格率です。プログラムと同じでfという関数(ここではロジスティック回帰)に、変数x(国語の点数や数学の点数のような説明変数)を引数にとり、合格率の予測結果を返します。

ここでxは配列のように複数の値を持つことができ、具体的には国語の点数や数学の点数などになります。式を見ると分かるように、βとxは掛け算されています。βは回帰係数と呼ばれ、国語の点数や数学の点数が合否に与える影響を調整します。

たとえば、国語の点数に対するβは2で数学の点数に対するβは0.5である時、国語の点数が 30点で数学の点数が50点の生徒においてβ⧵*xは、2⧵*30+0.5⧵*50=85となります。

また、αは切片に相当し変数xの影響を受けません。x、α、βによる計算結果を0から1の連続値になるように変換する式がロジスティック回帰になります。

f(x)を計算するには予測対象となるデータxの他に、αやβが必要です。これらの値は、訓練データの傾向を捉えることで得られます。このことを「学習する」と呼びます。

ロジスティック回帰で学習したモデルを使うことで、未知の事象に対して予測できるようになるのです。

f:id:itstaffing:20210113102524j:plain
ロジスティック回帰がどのようなものかがわかりました!
f:id:itstaffing:20210113102532j:plain
次回はECサイトのデータに対して、ロジスティック回帰を適用し、ユーザーが翌月に購買するか否かを予測してみましょう。
f:id:itstaffing:20210113102524j:plain
次は、いよいよ実践編ですね!がんばるぞ~!

第1話 機械学習の仕事内容って?実はコードを書くだけじゃない!
第2話 人工知能、機械学習、ディープラーニングの違いとは?
第3話 機械学習の活用事例!建設機械や回転寿司屋でも活用されている!?
第4話 機械学習したいのにデータがない!?
第5話 集計と可視化:pandasでデータの加工をしてみよう
第6話 続!集計と可視化:Plotlyでデータをグラフ化して傾向をとらえよう

 

【筆者】
早川 敦士さん
株式会社FORCASの分析チームにてリーダーを務める傍らで、株式会社ホクソエムで執行役員として従事。新卒でリクルートコミュニケーションズに入社しWeb広告やマーケティングオートメーションなどのB2Cマーケティングを経験し、FORCASではB2Bマーケティングプラットフォームのデータ分析および開発を担当している。大学在学中に『データサイエンティスト養成読本』(技術評論社刊)を共著にて執筆。その後も『機械学習のための特徴量エンジニアリング』(オライリー・ジャパン刊)や『Pythonによるはじめての機械学習プログラミング』(技術評論社刊)などで執筆活動を続けている。国内最大級のR言語コミュニティであるJapan.Rを主催。Youtubeチャンネル『データサイエンティストgepuro』で動画を投稿。
・Twitterアカウント

湊川 あいさん
フリーランスのWebデザイナー・漫画家・イラストレーター。マンガと図解で、技術をわかりやすく伝えることが好き。 著書『わかばちゃんと学ぶ Git使い方入門』『わかばちゃんと学ぶ Googleアナリティクス』『わかばちゃんと学ぶ Webサイト制作の基本』『運用ちゃんと学ぶ システム運用の基本』『わかばちゃんと学ぶ サーバー監視』が発売中のほか、マンガでわかるGit・マンガでわかるDocker・マンガでわかるRuby・マンガでわかるScrapbox・マンガでわかるLINE Clova開発・マンガでわかる衛星データ活用といった分野横断的なコンテンツを展開している。
・Amazon著者ページ
・Twitterアカウント

  わかばちゃんが登場する書籍いろいろ   

f:id:itstaffing:20210113102514j:plain  f:id:itstaffing:20210113102516j:plain
 
f:id:itstaffing:20210113102519j:plain  f:id:itstaffing:20210113102521j:plain


わかばちゃんと学ぶシリーズ(Amazonページ)