ホワイトリストルール追加のお知らせ
Imagenet等汎用的に使われる学習済みモデルが、テストデータ使用不可の制約にかかる可能性があるとのご指摘を受け、ルールを追加いたしました。下記ホワイトリストについては、たとえテストデータとの被りが含まれる場合も使用可とさせていただきます。
ホワイトリスト
なお、本コンペにおいては、当初通り外部データ・学習済みモデル使用にあたる運営確認は不要です。ホワイトリストにないモデルの使用について、ご心配な場合はトピック等でお気軽にお問い合わせください。運営にて判断させていただきます。
日本では古くから源氏物語や伊勢物語などの文学作品が、絵巻物や絵本として出版されており、時代背景を反映した様々な人間模様が描かれてきました。
中でも登場人物の描かれ方は、当時の性差への考え方の他、平民、武士、貴族といった身分制度に強く影響されており、現代とは大きく異なる、特徴的な描かれ方がされています。
例えば、貴族や皇族、その従者などの人物は、「下膨れの顔」「一重の目」「小さな口」等の、引目鉤鼻(ひきめかぎはな)と呼ばれる共通の特徴をもって描かれることが一般的です。この特徴は身分の低い人物の肖像画では見られ無いものになります。
引目鉤鼻は、「読者である貴族に対して、自分と近しい登場人物を親しみやすく描いた」「抽象的な表現であることが高貴さを表す表現として認識されていた」等、所以については諸説あります。
引目鉤鼻の例(源氏物語「夕霧」より)
こうした人物の描き方の特徴は、人文科学の分野では考察が進められており、当時の風俗や価値観に対して理解を深める手掛かりになることもあります。
今回は、絵巻物や絵本のデータから登場人物を分類するタスクに取り組んでいただきます。コンペティションで扱うデータとしては、人文学オープンデータ共同利用センター(CODH)の提供する、顔貌データを用いております。
1位 100,000円
※ 対象者には、コンペティション終了後メールにて連絡いたします
終了 2022/8/7 22:00 JST
LB公開 2022/8/7 24:00 JST
データをダウンロードするにはログインまたはユーザー登録して下さい
コンペに使用するデータは2つに分けられます。
これらのデータは『顔コレデータセット』(CODHが国文学研究資料館・ROIS-DS人文学オープンデータ共同利用センター、慶應義塾大学、京都大学附属図書館から収集、DOI:10.20676/00000353)を訓練データとテストデータに分割し、訓練データにラベルを付加したものです。
訓練データとテストデータはそれぞれ6,446件、2,000件のデータが含まれております。
npzファイルのarr_0
には256x256x3の画像が含まれます。arr_1
にはデータラベル(0: noble, 1: warrior, 2: incarnation, 3: commoner)が含まれます。
npzファイルのarr_0
には256x256x3の画像が含まれます。
※顔コレデータセットを活用した研究成果を発表する際には、以下の論文の引用をご検討下さい。
Yingtao Tian, Chikahiko Suzuki, Tarin Clanuwat, Mikel Bober-Irizar, Alex Lamb, Asanobu Kitamoto, "KaoKore: A Pre-modern Japanese Art Facial Expression Dataset", arXiv:2002.08595.
各画像中の人物の身分(y)について、整数値で予測してください。
回答用のsubmission.csvを用意する(エントリーとヘッダー行を含む) 。
提出されたファイルに余分な行や列(idとy以外)が含まれていた場合はエラーとなります。
提出ファイルは以下の列のみを含んでください:
以下は提出ファイルの例です。
id,y
1, 0
2, 1
3, 3
4, 0
...
本コンペでは、開催期間終了後 賞金対象者のコードを公開し、ユーザーの皆様にチーティング有無をレビューしていただき順位確定させる、オープンレビュー方式のコンペティションを行います。
コード公開後1週間:
レビュアー(ユーザー)より、チーティングの疑いに関するコメントがある場合は、ご回答をお願いいたします。
※チーティングとは無関係のコメント(ノウハウに関する質疑 等)についてもご回答いただけると幸いですが、順位確定の判断材料とは致しません。
レビュアーからの質疑と、回答状況をふまえて、最終的に運営側で順位確定を判断します。
開始日 2022/5/16 0:00 JST
終了日 2022/8/7 22:00 JST
LB公開 2022/8/7 24:00 JST
エントリー締め切り なし
ユーザー間での情報共有
コンペティションに関連するコード・データを、チーム外のユーザーと共有することはできません。全参加者が利用できる場合に限り、共有可能です。
外部データ/学習済みモデルの使用
本コンペティションの基本情報/データから取得できるデータのみを用いてチャレンジして下さい。
ただし、コンペ外データ(人文学オープンデータ共同利用センター公開データが明示的に含まれているものは除く)を用いて学習された学習済みモデルの使用は可能とします。
※コンペ期間中であっても、不正が疑われる場合は、運営より確認のためメール連絡させていただくことがございます。一週間以内にご回答いただけない場合も、不正と判断させていただきます。
以下ライブラリについては、ホワイトリストとし、たとえテストデータとの被りが含まれる場合も、使用に際して不正とはみなされないものとします。
ホワイトリストにつきましては下記URLより参照ください。
・ホワイトリスト
https://docs.google.com/spreadsheets/d/1GSOeYEl0inJdrbt00ERrKpNWJf2sTMwggOG0crvP49Y/edit?usp=sharing
本コンペにおいては、ライブラリの使用にあたる運営確認は不要ですが、ホワイトリストにないツールの使用に際してご心配になられることもあるかと存じます。
その場合は運営にて、ホワイトリストへの追加を判断いたしますので、お気軽にお問い合わせいただけましたらと存じます。
※注意事項
公平性の担保、チーティング等の不正防止のため、予告なくルールの追加・変更を行う場合がございます。
ご不便をおかけすることもあるかと思いますが、サービス向上のためご了承ください。
はい。
最も精度の高い学習モデルを作成した優勝者には、賞金10万円を贈呈します。
順位確定までのプロセスについては、ルール「Open Review Competition」を参照ください。
可能です。チームページから作成いただけます。
こちらから作成いただけます。
コンペティション参加にはアカウント登録が必要となりますのでご注意ください。
Seed を固定することが推奨です。
ただし、Seed を固定しなくても提出用コードとしては認めています。
ファイル提出後、23時間ごとにリセットとなります。
グローバル展開していくにあたり、居住国(時差)による有利・不利を最小化するため、一定時間でリセットする仕様としております。
このチュートリアルではkaokoreデータに対して
を行います
まずは必要なライブラリをインポートしましょう。
import numpy as np
import pandas as pd
import torch
from torch import nn, optim
import torchvision
from torchvision import models
import torchvision.transforms as transforms
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
! python --version
Python 3.7.4
print('numpy', np.__version__)
print('pandas', pd.__version__)
print('matplotlib', matplotlib.__version__)
print('torch', torch.__version__)
print('torchvision', torchvision.__version__)
numpy 1.17.4
pandas 1.0.2
matplotlib 3.1.3
torch 1.4.0
torchvision 0.5.0
まずはデータの読み込みをしてみましょう。
このコンペでは画像とラベルの組み合わせからなる学習データ(train_data.npz
)と
画像のみを含むテストデータ(test_data.npz
)が提供されています。
npzファイルをnp.load
関数を用いて読み込みます。
data_dir = '../compe_data/'
train_X, train_Y = np.load(data_dir + 'train_data.npz').values()
読み込まれたデータは(データ数, 高さ, 幅, チャンネル)
の順番で格納されています。
pytorchで利用できる形式である(データ数, チャンネル, 高さ, 幅)
の順に変更します。
train_X = train_X.transpose((0, 3, 1, 2))
pytorchではDataLoader
を用いることで、バッチごとにデータを取り出すことができます。
train_data = torch.utils.data.TensorDataset(torch.from_numpy(train_X).float(), torch.from_numpy(train_Y.astype(np.int64)))
train_loader = torch.utils.data.DataLoader(train_data, batch_size=64, shuffle=True)
作成したtrain_loader
を用いていくつかデータを表示してみます。ここではmatplotlib
を用いてプロットをします。
class_names = ('noble', 'warrior', 'incarnation', 'commoner')
def imshow(data, title=None):
"""Imshow for Tensor."""
data = data.numpy().transpose((1, 2, 0))
data = (data / 255)
data = np.clip(data, 0, 1)
plt.imshow(data)
if title is not None:
plt.title(title)
# DataLoaderからバッチを取り出す
inputs, classes = next(iter(train_loader))
# 4つだけ表示する
out = torchvision.utils.make_grid(inputs[:4])
imshow(out, title=[class_names[x] for x in classes[:4]])
DNNのフレームワークであるpytorchを用いてCNNを作成して分類をおこなっていきます。
まず、GPUを用いてCNNの学習を行いたいのでCUDAが利用可能な場合にはCUDAを有効にします。
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
torchvisionはpytorchのパッケージで画像認識において頻繁に使われるネットワークアーキテクチャや学習済みモデル、データセット、前処理などの機能を提供しています。
今回はtorchvisionに含まれるresnet18
というモデルを用いて学習を行います。
model = models.resnet18()
今回は4クラスの分類を行うのでネットワークの最終層の出力の次元数を変更します。
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 4)
作成したmodel
をGPUへ転送します。
model = model.to(device)
損失関数と最適化アルゴリズムを設定します。分類問題のためクロスエントロピー損失関数を利用し、
最適化アルゴリズムにはSGDを利用します。
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
ここから、実際にモデルの学習を行っていきます。to
メソッドによって入力とラベルをGPUへ転送しています。optimizer.zero_grad()
を呼び出して、ネットワークの各パラメータに保存されている勾配情報を初期化します。
モデルの出力outputs
と正答ラベルlabels
から
損失関数の値を計算します。loss.backward()
によって誤差逆伝播を行い各パラメータの勾配を更新します。optimizer.step()
によって更新された勾配を元にパラメータの値を更新します。
log_interval = 10
for epoch in range(10):
running_loss = 0.0
for i, data in enumerate(train_loader, 0):
inputs, labels = data
inputs /= 127.5
inputs -= 1.0
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % log_interval == (log_interval - 1):
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss / (log_interval)))
running_loss = 0.0
print('Finished Training')
[1, 10] loss: 1.333
[1, 20] loss: 1.195
[1, 30] loss: 1.009
[1, 40] loss: 1.346
[1, 50] loss: 1.267
[1, 60] loss: 1.018
[1, 70] loss: 1.146
[1, 80] loss: 1.160
[1, 90] loss: 1.046
[1, 100] loss: 1.219
[1, 110] loss: 1.264
[1, 120] loss: 1.119
[1, 130] loss: 1.164
[1, 140] loss: 1.089
[1, 150] loss: 1.310
[1, 160] loss: 1.244
[1, 170] loss: 1.220
Finished Training
学習したモデルを用いて学習データに対する正答率を見てみましょう。
モデルの出力はあるクラスに属する確率値のようなものなのでtorch.max
関数を用いて各出力で最も大きい値を持つインデックスを取得します。
この予測されたラベルを用いて正答率を計算します。
correct = 0
total = 0
wrong_data = []
with torch.no_grad():
for data in train_loader:
images, labels = data
images /= 127.5
images -= 1.0
images, labels = images.to(device), labels.to(device)
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('accuracy', 100 * correct / total)
accuracy 79.59975178405213
学習データにおける正答率は80%程度でした。
続いて誤識別したデータを確認します。
正答率を求めたときとは逆に、予測されたラベルが正答ラベルとことなるデータのインデックスを取得し、プロットします。
grid = torchvision.utils.make_grid(images[predicted != labels].cpu()[:5])
grid += 1.0
grid *= 127.5
imshow(grid, title=['predict:'+ str(pred.item())+' actual:' + str(truth.item()) for pred, truth in zip(predicted[predicted != labels][:10], labels[predicted != labels].data)][:5])
このモデルでは、後姿を誤認識してしまい”化身”と認識してしまうことがあるようです。
最後にテストデータを用いて提出データを作成します。
学習データと同様にtest_data.npz
を読み込み、DataLoader
を作成します。
test_X = np.load(data_dir + 'test_data.npz')['arr_0']
test_X = test_X.transpose((0, 3, 1, 2))
test_data = torch.utils.data.TensorDataset(torch.from_numpy(test_X).float())
test_loader = torch.utils.data.DataLoader(test_data, batch_size=64, shuffle=True)
predicts = []
with torch.no_grad():
for x in test_loader:
x = x[0]
x /= 127.5
x -= 1.0
x = x.to(device)
out = model(x)
_, predicted = torch.max(out.data, 1)
predicts.append(predicted.cpu().numpy())
提出データはid
,y
のカラムを持つcsvファイルとします。
sub = pd.DataFrame(np.concatenate(predicts), columns=['y'])
sub.index.name = 'id'
sub.index += 1
sub.to_csv('submission.csv')
コンペティションへの参加に際しては、ProbSpace利用規約(以下、「利用規約」といいます。)に加え、本ProbSpace参加規約(以下「本規約」といいます。)に同意いただく必要があります。利用規約にて定義された用語は、本規約においても同様の意味で用いられるものとします。
第1条(適用)
第2条(定義)
本規約において次の各用語の定義は、それぞれ以下に定めるとおりとします。
第3条(権利の帰属)
第4条(入賞者の義務)
第5条(禁止事項)
第6条(本コンペの変更、中断、終了等)
第7条(損害賠償)
第8条(本規約の変更)
当社は、必要と判断した場合には、参加者に対して事前に通知する(本コンペにかかる当社ウェブサイト上での告知その他当社が適当と認める方法を含みます。)ことにより、いつでも本規約を変更することができるものとします。なお、変更内容の通知後、参加者が当社の定める期間内に本コンペへの参加を取り消す手続をとらなかった場合には、当該参加者は変更後の規約に同意したものとみなされます。当社は、本規約の変更により参加者に生じたすべての損害について一切の責任を負いません。
第9条(その他)
本契約の準拠法は日本法とし、本契約に起因し又は関連する一切の紛争については、当社の本店所在地を管轄する裁判所を第一審の専属的合意管轄裁判所とします。
(制定)2020年6月22日