環境編:VS CodeからPythonでKaggle APIを呼び出してみよう:僕たちのKaggle挑戦記
Pythonのプログラム中で、kaggleパッケージをインポートして、コマンドラインではなくコードからKaggle APIにアクセスしてみます。役に立つかな?
前回は、Kaggleが提供するkaggleパッケージをインストールして、Visual Studio Code(以下、VS Code)の統合ターミナルからコマンドラインを使ってKaggle APIにアクセスしてみました。今回はkaggleパッケージを使ってPythonのコードからKaggle APIにアクセスしてみます。
と書いたのはよいのですが、正直、コマンドラインを使えば十分じゃないか? という気にはなります。なお、Kaggle APIのアクセスには何らかのリミットが設けられているようです。使いすぎにはご注意ください。[かわさき]
意見が違って面白いですが、私の場合は、結局、リーダーボードなど見たりするので、基本的な作業はKaggle Webサイト上で行うのが一番快適だと感じています。
一方で、「Submissionの自動化」だけに限定してKaggle APIが便利だと感じています。Submission時のメッセージもコードで自由にカスタマイズできるので、コマンドよりも扱いやすいです。Submissionは何度も行う作業ですが、データセットのダウンロードなどは一度切りの作業なので、Kaggle APIだけでなくコマンドを使うことにもあまりメリットを感じていないですね。
とはいえ、人によっては全く違う意見かもしれません。あくまで僕個人の感想なので、参考程度で見ていただけるとうれしいです。冒頭からコメントを書きすぎですね。ごめんなさい。[一色]
Kaggle API
前回も述べましたが、Kaggle APIを使うには「pip3 install kaggle」などのコマンドを実行して、kaggleパッケージをインストールしておく必要があります。このときに、Windows環境でkaggleコマンドを使うのであれば、該当するコマンドにパスを通しておく必要があります。簡単なのは仮想環境を作り有効化した上で、そこにkaggleパッケージをインストールすることです。ここでは詳細な手順は省略します(今回はWindows環境で仮想環境を作成し、そこにkaggleパッケージをインストールしています)。
加えて、クレデンシャルを取得しておく必要もあります。これには、Kaggle公式サイトで自分のアカウントページを表示して、[API]セクションで[Create New API Token]ボタンをクリックします。
ボタンをクリックすると、kaggle.jsonファイルがダウンロードされるので、これを「~/.kaggle/kaggle.json」(macOSを含むUNIX系のOS)または「C:\Users\<ユーザー名>\.kaggle\kaggle.json」(Windows)として保存しておきましょう。
この手順については前回の記事でもう少し詳しく触れているので、そちらも参考にしてください。
Pythonのコードからkaggle APIにアクセスするには
PythonのコードからKaggle APIにアクセスするには、kaggleパッケージをインポートして、そこからKaggleAPIクラスのインスタンスメソッドを呼び出す形になります。簡単なのは次のように、kaggleパッケージが提供するapiオブジェクトをインポートすることです。
from kaggle import api
print(type(api)) # <class 'kaggle.api.kaggle_api_extended.KaggleApi'>
このapiオブジェクトはkaggleパッケージの__init__.pyファイルで定義されていて、認証まで済んでいます。
あるいは次のように明示的にKaggleApiクラスのインスタンスを生成してもよいでしょう。この場合にはauthenticateメソッドを呼び出して、アカウントの認証を行っておく必要があります。
from kaggle import KaggleApi
api = KaggleApi()
api.authenticate()
print(type(api)) # <class 'kaggle.api.kaggle_api_extended.KaggleApi'>
KaggleApiクラスのインスタンスを入手して認証が済めば、後はこのインスタンスのメソッドを呼び出すだけです。
よく使いそうなものをざっくりとまとめておきましょう。
メソッド | 説明 |
---|---|
competitions_list | コンペティション(以下、コンペ)一覧の取得 |
competition_list_files | 指定したコンペで用意されているデータファイル一覧の取得 |
competition_download_file | 指定したコンペの指定したデータファイルをダウンロード |
competition_download_files | 指定したコンペの全てのデータファイルをダウンロード |
competition_submit | 指定したファイルを推測結果としてKaggleにサブミット |
dataset_list | Kaggleに登録されたデータセットの一覧を取得 |
dataset_metadata | データセットのメタデータをダウンロード |
dataset_list_files | データセットに含まれるファイルの一覧を取得 |
dataset_download_files | 指定したデータセットの全ファイルをダウンロード |
dataset_download_file | 指定したデータセットの指定したファイルをダウンロード |
kernels_list | カーネル一覧の取得 |
kernels_pull | カーネルからファイルをダウンロード |
kernels_output | Kaggle上で直近にカーネルを実行した結果を取得 |
kernels_push | カーネルへファイルをアップロード |
KaggleApiクラスが提供するメソッド(一部) |
これらは主にkaggleコマンドに対応するものとなっていますが、competitionsとcompetitionのように単数形と複数形のメソッドがあることには注意してください(複数形は対象の数が不定の場合で、単数形は引数で対象を絞るといった違いがあるようです)。また、筆者の環境(macOS/Windows)ではkernels_pushメソッドは例外が発生したので動作の確認はできていません。
というわけで、これらのAPIをPythonコードから呼び出してみることにします。ここでは、以下に示すセルが3つだけのノートブックを用意しました(Kaggle APIにアクセスすることが重要であり、Kaggleのコードはどうでもいいですよね)。
Titanicコンペのデフォルトのデータセットと、それを基に自分が作成したデータセットがあることには注意してください。
コンペ一覧とデータセットの取得
では、Titanicコンペを検索して、そこで必要になるデフォルトのデータセットをダウンロードしてみましょう。
既に述べたように、コンペの一覧を取得するにはcompetitions_listメソッドを使います。
competitions_list(group=None, category=None, sort_by=None, page=1, search=None)
searchパラメーターには検索したコンペに含まれそうな綴(つづ)りを、categoryパラメーターにはgettingStarted/research/recruitment/masters/playgroundなどの語を与えます。以下に例を示します。
competitions = api.competitions_list(search='titanic')
for competition in competitions:
print(competition.ref)
VS Codeの統合ターミナル(REPL環境)で実行した結果を以下に示します。
Pythonコードを見ると、Pylanceが「ref」なんて属性ないよ、といっていますがあるんです。
competitions_listメソッドの戻り値はKaggle APIが提供するCompetitionクラスのインスタンスを要素とするリストです。「dir(competitions[0])」などを実行すれば分かりますが、このオブジェクトにはさまざまな属性があります(実際には以下のコードでアクセスしているよりも多くの属性があります)。そこで以下のようにして、「kaggle competitions list」コマンドと似た出力を得ることもできます。
result = [
'ref deadline category reward teamCount Entered',
'----------------- ---------- --------------- --------- --------- -------'
]
for competition in competitions:
r = competition.ref
d = str(competition.deadline).split(' ')[0]
c = competition.category
rw = competition.reward
t = competition.teamCount
u = competition.userHasEntered
s = f'{r:17} {d:10} {c:15} {rw:9} {t:9} {u:7}'
result.append(s)
print('\n'.join(result))
実行結果を以下に示します。
ここでも怒られていますが、大丈夫。それらの属性、ありますから。
wwww(わらわらわらわら)
コンペ情報で必要になるのは、ref属性です(上の一覧で一番左に表示されています)。コンペで用意されているデータセットをダウンロードするときには、これを指定します。というわけで、competition_list_filesメソッドでデータセットを検索してみましょう。このメソッドには、今述べたコンペを識別する名前を指定します。
competition = competitions[0].ref
file_list = api.competition_list_files(competition)
for file in file_list:
print(file.name)
実行結果を以下に示します。
おなじみの3つのファイルが得られました(戻り値はKaggleが提供するFileクラスのインスタンスを要素とするリストです)。
データファイルをダウンロードするには、competition_download_fileメソッドかcompetition_download_filesメソッドを使用します。個別にファイルをダウンロードするなら前者を、ZIPファイルにまとめてダウンロードするなら後者を使えばよいでしょう。ダウンロードするコードは以下の通りです。
# competition_download_fileメソッド
for file in file_list:
api.competition_download_file(competition, file.name, path='input/titanic')
# competition_download_filesメソッド
import shutil
api.competition_download_files(competition, path='input')
shutil.unpack_archive('input/titanic.zip', 'input/titanic')
どちらのメソッドでもコンペ名を最初に指定します。competition_download_fileメソッドでは次にダウンロードするファイルを指定しますが、これには上で見たcompetition_list_filesメソッドの戻り値であるFileオブジェクトのname属性が使えます。pathにはダウンロード先のディレクトリを指定します。Kaggleのファイル配置と同じになるように気を付けましょう。
データセットの検索とダウンロード
以前に自分(や他のユーザー)が作成し、Kaggleに登録してあるデータセットは「dataset_」で始まる名前のメソッドを使って操作できます。自分が作成したデータセットを一覧するには、dataset_listメソッドを呼び出します。
dataset_list(sort_by=None, size=None, file_type=None, license_name=None,
tag_ids=None, search=None, user=None, mine=False, page=1,
max_size=None, min_size=None
このメソッドには上に示したように多くのパラメーターを持ちますが、ここでは自分が作成したものだけを一覧してみます。これにはuserパラメーターに自分のアカウントを指定するか、mineパラメーターにTrueを渡します。
例を以下に示します。
datasets = api.dataset_list(mine=True)
for dataset in datasets:
print(dataset.ref)
前回と同様に3つのデータセットが得られます。
なお、このメソッドの戻り値はKaggle APIが提供するDatasetクラスのインスタンスを要素とするリストで、さまざまな属性を持っています。中でも重要なのが、先ほどと同様、ref属性です(上のコード例でも使っていますね)。データセットでは「アカウント名/識別子」という形でそれぞれを識別するようになっています。
ここでは一番上にある「my-titanic-data」というデータセットをダウンロードすることにします。このデータセットにはmytrain.csvとmytest.csvの2つのファイルが含まれていますが、これら2つのファイル名をコードで取得するにはdataset_list_filesメソッドを使います。このメソッドに上述の「アカウント名/識別子」を渡せば、対応するデータセットに含まれるファイルが返されます。ここではそれをfiles属性でそのまま取り出してみましょう。
ds = datasets[0]
file_list = api.dataset_list_files(ds.ref).files
for file in file_list:
print(file.name)
このメソッドを呼び出してfiles属性を取り出すと、Kaggle APIが提供するFileクラスのインスタンスを要素とするリストが得られます。この感じで、ファイルを個別にダウンロードするには次のようになります(変数dsにデータセットを代入していますが、これはページの横幅の都合です)。
for file in file_list:
api.dataset_download_file(ds.ref, file.name, path='input/my-titanic-data')
これを実行すると、「input/my-titanic-data」ディレクトリがなければ作成されて、そこに2つのCSVファイルがダウンロードされます。
あるいは、dataset_download_filesメソッドで複数のファイルをまとめてダウンロードして、後から展開する方法もあります。コードは次のようになります。
ds = datasets[0]
api.dataset_download_files(ds.ref, path='input/my-titanic-data', unzip=True)
dataset_download_filesメソッドにはunzipパラメーターがあり、これにTrueを渡すと展開も行ってくれます(便利)。
ここまで丁寧に書いてきましたが、実は使わないんです(笑)。あくまでもKaggle APIにはこんな風にアクセスするというのを知るためのものだと思ってください。
カーネル
カーネルについても、ここまで見てきたのとほぼ同様な使い勝手になります。なので、早足で見ていきましょう。カーネルの一覧はkernels_listメソッドを呼び出すことで取得できます。
kernels_list(page=1, page_size=20, dataset=None, competition=None,
parent_kernel=None, search=None, mine=False, user=None,
language=None, kernel_type=None, output_type=None, sort_by=None)
ここでも自分が作成したカーネルだけを一覧してみます。コードは次の通りです。
kernels = api.kernels_list(mine=True, competition=competition)
for kernel in kernels:
print(kernel)
実行結果を以下に示します。
ここでは、少し下にある「gender_submission」というカーネルからファイル(ノートブック)をダウンロードしましょう。これには、kernels_pullメソッドに先ほどと同様、上で取得したKernelオブジェクトのref属性とダウンロード先のディレクトリを渡してやります。
for k in kernels:
if k.title == 'gender_submission':
kernel = k
break
api.kernels_pull(kernel.ref, path='notebook', metadata=True)
これにより、notebookディレクトリにノートブックがダウンロードされます。「metadata=True」としているのは、このノートブックに手を加えて、Kaggleにプッシュする際に使用するメタデータを同時にダウンロードするための指示です。
ここまでくれば、このカーネルのコードを実行する準備ができたといえるでしょう。とはいえ、kaggleパッケージからコードを実行する方法はないようなので、ここはVS CodeのUIを使ってコードを実行すると、mysubmission.csvファイルが作成されるはずです(実行前には、カーネルとして使用するPythonの指定などを行う必要もあります)。
後は、このCSVファイルをサブミットするだけです。これにはもちろん、competition_submitメソッドを使用します。このメソッドにサブミットするCSVファイルの名前、メッセージ、それからコンペの名前を指定します。
file = 'notebook/mysubmission.csv'
msg = 'hello from python code in vscode'
competition = 'titanic'
api.competition_submit(file, msg, competition)
以上で、推測結果のサブミットまでができました。本来はこれまでの自分のサブミットを取得するcompetition_submissionsメソッドや、指定したカーネルを直近にKaggleで実行した結果を取得するkernels_outputメソッドなど、役に立ちそうなメソッドがありますが、これらの調査については読者にお任せしましょう。
前回と同様な内容を、ここまでPythonのコードを使って行ってきましたが、さて、これは便利なのでしょうか。筆者なら素直に統合ターミナルのコマンドラインからKaggle APIにアクセスするかなーと感じました。
僕の感想では、冒頭にも書いたように「Submissionを自動化したい人」に限定すればKaggle APIはお勧めですね。例えば手法やアーキテクチャを変えながら5パターンなど複数の機械学習モデルを作成しようとするケースで、それら学習にそれぞれ20時間以上など長時間がかかる場合には、Submissionまで自動化しておけば、毎日の作業はリーダーボードを見るだけになり、個人的には気が楽ですね(実際に自動化した記憶があります)。Pythonコードで作業を自動化しておいて、それが動くのを眺めてコーヒーを飲みながらまったりするのが大好きですので。
とはいえ、Webサイト(GUI)を使いたい、コマンドを使いたい、Kaggle APIを使いたい、など人それぞれ違ってよいと思うので、僕の感想は横に置いておいて好きにやるのが一番良いと思います。
あと前回の最後に書かれていた「Kaggleノートブックのアップロード」について思いだしたことをここで書いておきます。そもそも手元でファイルを管理しているので、あまりKaggleノートブックとしてアップロードしていませんでした。アップロードするときも、Kaggleノートブック環境(GUI)のメニューから「ノートブックのインポート」を実行して既存のノートブックを上書きするようにしていました。.ipynbファイルを選択するだけで、手間もほとんどありません。当然ながらWindowsとコマンド(やKaggle API)の相性問題もないので、「Kaggleノートブックのアップロード」にはWebサイト(GUI)を使うのがお勧めです。
Copyright© Digital Advantage Corp. All Rights Reserved.