記事の説明
Signate Student Cup2020というデータサイエンスコンペティションに大学のゼミで参加した際に作成したソースコードを見つけたため、どんな実装をしていたかを説明していきたいと思います。
なるべく初学者の方にも分かるようにしたいため、複雑な箇所は一部割愛します。
Signate Student Cup2020
大会概要
株式会社Signateが定期的に開催しているデータサイエンススキルを競い合う学生限定のコンペティションです。
各コンペティションごとに異なるお題が提示され、そのお題に沿って分析や予測の正確さを競い合います。
私は2020年の夏に開催された予測部門に参加しました。
2020年夏の大会内容
2020年夏のお題は英語圏の求人情報に含まれるテキストデータをもとに、その職務内容がデータサイエンティスト、機械学習エンジニア、ソフトウェアエンジニア、コンサルタントのいずれに分類されるのかを予測するという内容でした。
参加者には最初に、csv形式で訓練用データ(train.csv)とテスト用データ(test.csv)が渡されます。
訓練用データには2930 人分の求人情報と職種が記載されています。職種はデータサイエンティスト、機械学習エンジニア、ソフトウェアエンジニア、コンサルタントの4種類で、それぞれ1、2、3、4と数字で表記されています。
テスト用データには1742人分の求人情報だけが記載されており、訓練用データを職種の割り振り方を学習、予測するアルゴリズムを作成しました。
テスト用データの職種を予測し、その予測の正確さを競い合うのが今回のコンペティションの趣旨でした。
参考URL
https://signate.jp/competitions/281
実装したソースコードの説明
以下のソースコードはJypter Notebookを使用して、pythonで書いております。
#必要なライブラリのインポート
import numpy as np
import pandas as pd
from pandas import Series, DataFrame
from sklearn.feature_extraction.text import CountVectorizer,TfidfVectorizer
from sklearn.svm import LinearSVC
numpyは数値計算用ライブラリ、pandasはデータ処理用のライブラリ、sklearnは機械学習用のライブラリです。
#データの読み込み
train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")
#先頭確認
train.head()
#trainの職種ごとの数を調べる
train["jobflag"].value_counts()
訓練用データとテストを取り込んで変数に格納してから、訓練用データの先頭データがどうなっているかとそれぞれの職種が何個ずつあるかを確認しています。
#職種ごとの数
3 1376
1 624
4 583
2 348
Name: jobflag, dtype: int64
1:データサイエンティスト、2:機械学習エンジニア、3:ソフトウェアエンジニア、4:コンサルタントのため、ソフトウェアエンジニアが一番多く、機械学習エンジニアが一番少ないのが確認できました。
#訓練データとテストデータに分ける
X_train = pd.DataFrame(train["description"])
Y_train = pd.DataFrame(train["jobflag"])
X_test = pd.DataFrame(test["description"])
訓練用データから説明文と職種を、テスト用データから説明文を抽出しています。
#単語の出現頻度で職種を識別する
#使用するモデルはLinearSVC
tf_vec = TfidfVectorizer() #tf-idf
#transform()を使用してトレーニングデータをベクトル化
X_train_tfidf = tf_vec.fit_transform(X_train["description"])
TfidfVectorizer()とはテキストデータから特徴量を作成するためのツールです。
ここではテキストデータ内の単語の出現頻度と、文章内に出てくる単語の珍しさ(あまり出てこない単語)の重要度を数値化しています。
transform()メソッドというのは機械学習で特徴量を数値データに変換するためのメソッドです。
今回は説明文のテキストデータを数値化しています。
テキストデータを数値化することでモデルが学習できるようにしています。
# LinearSVCモデルの構築と学習
model = LinearSVC()
model.fit(X_train_tfidf, Y_train)
LinearSVCとはサポートベクターマシンと呼ばれる機械学習アルゴリズムの一つで、分類や回帰分析の際によく使用します。
データをLinear(線形)で表して分類を行います。
数学のx軸とy軸のある二次元グラフや、z軸を加えた3次元グラフにデータを落とし込んで分類するイメージです。(3次元以上の場合もあります。)
このLinearSVCで訓練用のベクトル化したテキストデータ(x_train_tfidf)と職種(Y_train)を用いてモデルを学習させています。
ここまででひとまずは学習済みモデルの完成です。
※備考
LinearSVCは引数にパラメータを渡すことができます。
グリッドサーチと言われる総当たりの手法で最適化されたパラメータを取得して、そのパラメータを渡すとまた学習の結果も変わります。
本番ではここでグリッドサーチを行ってパラメータを渡していましたが、今回は初学者の方にも分かりやすくしたいため、グリッドサーチについては割愛します。
グリッドサーチについて興味のある方は以下の記事を参考にしてください。
参考URL
https://qiita.com/Takayoshi_Makabe/items/d35eed0c3064b495a08b
# 評価用データで予測
X_test_tfidf = tf_vec.transform(X_test)
predictions = model.predict(X_test_tfidf)
predict()というのは機械学習モデルを使用して、新しいデータに対する予測を行うメソッドです。
ここではテスト用データの特徴量を分析できるように数値化して、学習済みモデルを使用して職種の予測を行っています。
#csvに新しいをカラム追加して予測結果を挿入する
test["jobflag"] = predictions
#職種数をカウントする
test["jobflag"].value_counts()
#予測結果
3 992
1 389
4 278
2 84
Name: jobflag, dtype: int64
これで予測が完了しました。
訓練用データの時と同様にソフトウェアエンジニアが一番多く、機械学習エンジニアが一番少ないです。
#予測結果をcsv形式にする
test.to_csv("predictions.csv", index=False, encoding="utf_8_sig")
こうしてcsv形式でエクスポートしたデータをコンペティション参加者専用ページから提出すると、その時点での点数と順位が分かるようになっていました。(1日に3回まで提出が可能で、期間中は毎日提出できました。)
大会結果
参加チーム308チーム中85位でした。
上位入賞者がどんな分析/予測を行ったかについて公式サイトに記載があったため、興味がある方は以下のリンクからご確認ください。
参考URL
https://signate.jp/competitions/281/summary
終わりに
久しぶりにデータ分析/予測のコードを見て、「こんなことしてたのか」や「これってどういう処理だったかな」ととても良い復習になりました。
Signateは他にもコンペティションを開催しているので、興味のある方は是非以下のURLからご確認ください。
参考URL
https://signate.jp/
明日は@piyorさんの記事が公開されます。
是非そちらもご覧ください。