2026 Spring Deep Learning course visual

Deep Learning Foundation Course

東京大学松尾・岩澤研究室が主催する公開講座で、ニューラルネットワークの基礎から自然言語処理や深層生成モデルまで、Deep Learning を基礎から実践的に学べる講座です。特別招待で学生に交じって参加中!!

Course Completed
Deep Learning 基礎講座 2026 Spring 修了証

Deep Learning 基礎講座の修了実績です。修了証(PDF)をご覧いただけます。

修了証を確認

Lecture2 Homework

更新者:demimomi 2026年4月25日 結果33位(最高5位) 全2,281名

Lecture2 では、単層のソフトマックス回帰という制約の中で、入力特徴量を丁寧に設計することで精度を高めた実装を掲載しています。

Lecture3 Homework

更新者:demimomi 2026年5月1日 結果90位(最高25位) 全2,158名

Fashion MNIST を NumPy だけで実装した多層パーセプトロンで分類し、前処理・学習安定化・推論時の工夫まで含めて、より実戦的な構成にしています。

標準化BatchNormLeaky ReLUDropoutTTA

Lecture4 Homework

更新者:demimomi 2026年5月9日 結果61位(最高10位) 全2,039名

Fashion MNIST の分類課題に対して、PyTorch を使いながらも高レベル API に頼りすぎない実装です。Dense 層、活性化関数、Dropout、損失関数を自前寄りに構成し、制約の中で学習の安定性と再現性を確保しています。

PyTorch自前実装AdamWEarly Stopping

Lecture5 Homework

更新者:demimomi 2026年5月22日 結果57位(最高5位) 全1,881名

Lecture5 では、CIFAR-10 の分類課題に対して、CNN ベースのモデルを PyTorch で実装しています。既存モデルや学習済みモデルに頼らず、WideResNet 系の CNN を自前で定義し、データ拡張・正則化・EMA・MixUp/CutMix・TTA を組み合わせて精度向上を狙いました。

WideResNetRandAugmentMixUp / CutMixEMATTA

※ ご要望に合わせて、lecture05_homework.py(スクロール表示)は削除しています。

Lecture6 Homework

更新者:demimomi 2026年6月7日 結果22位(最高2位) 全1,826名

Lecture6 では、VOC2011 データセットのセグメンテーション課題に対して、FCN 風のモデルを実装しています。backbone として ResNet101 を利用しつつ、torchvision.models.segmentation の完成済み FCN は使わず、複数階層の特徴を統合する独自ヘッドで 21 クラスのマスクを予測する構成です。

1. データ処理

画像は BILINEAR、マスクは NEAREST で 224×224 に変換。学習時はランダムスケール、ランダムクロップ、左右反転、ColorJitter を組み合わせています。

2. モデル構成

ResNet101 の layer1〜layer4 から特徴を取り出し、それぞれ 64ch に射影して結合。浅い特徴と深い特徴を合わせて FCN 風にセグメンテーションを行います。

3. Loss と評価

クラス不均衡を考慮した重み付き CrossEntropyLoss に Dice Loss を加え、評価指標として mean-IoU を計算しています。

4. 学習・推論の工夫

AdamW、CosineAnnealingLR、mixed precision、gradient clipping、early stopping を採用。推論時は multi-scale と horizontal flip の TTA で予測を安定化しています。

FCNVOC2011ResNet101 BackbonemIoUDice LossMulti-scale TTA

Lecture7 Homework

更新者:demimomi 2026年5月29日 結果29位(最高1位) 全1,779名

Hugging Face: matsuo-iwasawa-lab-dl-course-2026-hw07

Lecture7 では、IMDb の sentiment analysis 課題に対して、RNN 系モデルを用いた二値分類を実装しています。BiGRU、Attention、seed ensemble、threshold tuning を組み合わせ、F値の向上を狙っています。

1. 入力処理

テキスト系列を最大長で切り詰め、EOS と PAD を扱いながら DataLoader 用の collate 関数でバッチ化しています。

2. モデル構成

RNN 系モデルをベースに、双方向 GRU と Attention を組み合わせて系列全体から感情分類に有効な特徴を抽出します。

3. 学習・評価

BCEWithLogitsLoss、AdamW、ReduceLROnPlateau、Early Stopping を使い、validation macro F1 と最適 threshold を確認しながら学習しています。

4. 推論の工夫

複数 seed の結果を ensemble し、validation で得た threshold を平均して最終予測を作成しています。

RNNIMDbBiGRUAttentionF1 ScoreSeed Ensemble
lecture07_homework.py(スクロール表示)
# -*- coding: utf-8 -*-
"""lecture07_homework.ipynb
Automatically generated by Colab.
Original file is located at:
    https://colab.research.google.com/drive/1z1UgheoLYhrxhlewI2siinDwSYEhAJz8

Lecture 7 Homework: IMDb Sentiment Analysis
BiGRU + Attention + seed ensemble
ルール厳守:外部学習データ・事前学習Embeddingは使わない
"""

from google.colab import drive
drive.mount('/content/drive')
work_dir = 'drive/MyDrive/Colab Notebooks/DLBasics2026_colab'
!pip install portalocker
import os
import copy
import random
import numpy as np
import pandas as pd
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torch.nn.utils.rnn import pad_sequence, pack_padded_sequence, pad_packed_sequence
from torch.nn.utils import clip_grad_norm_
from sklearn.metrics import f1_score
from sklearn.model_selection import train_test_split
from typing import List
seed = 1234
torch.manual_seed(seed)
np.random.seed(seed)
random.seed(seed)

x_train = np.load(work_dir + '/Lecture07/data/x_train.npy', allow_pickle=True)
t_train = np.load(work_dir + '/Lecture07/data/t_train.npy', allow_pickle=True)
x_train, x_valid, t_train, t_valid = train_test_split(
    x_train, t_train, test_size=0.2, random_state=seed
)
x_test = np.load(work_dir + '/Lecture07/data/x_test.npy', allow_pickle=True)
# Hyper Parameters
秘密!
TRAIN_FINAL_ON_ALL = True
# Model
秘密2

def fix_seed(seed: int = 1234):
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
    torch.backends.cudnn.benchmark = True

def max_token_id(*arrays):
    m = 0
    for arr in arrays:
        for seq in arr:
            if len(seq) > 0:
                m = max(m, int(np.max(seq)))
    return m

word_num = max_token_id(x_train, x_valid, x_test) + 1
print(f"Vocabulary size: {word_num}")
def text_transform_v2(text, max_length=MAX_LEN):
    text = list(text)
    text = text[:max_length - 1] + [EOS_IDX]
    return text, len(text)
def collate_batch_v2(batch):
    label_list, text_list, len_seq_list = [], [], []
    for sample in batch:
        if isinstance(sample, tuple):
            label, text = sample
            label_list.append(float(label))
        else:
            text = sample
        text, len_seq = text_transform_v2(text)
        text_list.append(torch.tensor(text, dtype=torch.long))
        len_seq_list.append(len_seq)
    labels = torch.tensor(label_list, dtype=torch.float32)
    texts = pad_sequence(text_list, padding_value=PAD_IDX, batch_first=True).long()
    lengths = torch.tensor(len_seq_list, dtype=torch.long)
    return labels, texts, lengths
def make_loader(xs, ts=None, shuffle=False, seed=1234):
    dataset = list(xs) if ts is None else [(t, x) for t, x in zip(ts, xs)]
    generator = torch.Generator()
    generator.manual_seed(seed)
    return DataLoader(
        dataset,
        batch_size=batch_size,
        shuffle=shuffle,
        collate_fn=collate_batch_v2,
        pin_memory=torch.cuda.is_available(),
        generator=generator if shuffle else None,
    )
def get_pos_weight(labels):
    labels = np.asarray(labels).astype(int)
    pos = max(1, int(labels.sum()))
    neg = max(1, int(len(labels) - labels.sum()))
    return torch.tensor([neg / pos], dtype=torch.float32)
def find_best_threshold(y_true, y_prob):
    thresholds = np.arange(0.25, 0.751, 0.005)
    scores = [
        f1_score(y_true, (y_prob >= th).astype(int), average="macro")
        for th in thresholds
    ]
    best_i = int(np.argmax(scores))
    return float(thresholds[best_i]), float(scores[best_i])
def train_one_epoch(model, loader, optimizer, criterion, device):
    model.train()
    losses = []
    for label, line, len_seq in loader:
        x = line.to(device, non_blocking=True)
        t = label.to(device, non_blocking=True)
        lengths = len_seq.to(device, non_blocking=True)
        optimizer.zero_grad(set_to_none=True)
        logits = model(x, None, lengths)
        loss = criterion(logits, t)
        loss.backward()
        clip_grad_norm_(model.parameters(), max_norm=1.0)
        optimizer.step()
        losses.append(float(loss.detach().cpu()))
    return float(np.mean(losses))
@torch.no_grad()
def predict_proba(model, loader, device):
    model.eval()
    probs = []
    for _, line, len_seq in loader:
        x = line.to(device, non_blocking=True)
        lengths = len_seq.to(device, non_blocking=True)
        logits = model(x, None, lengths)
        prob = torch.sigmoid(logits)
        probs.append(prob.detach().cpu().numpy())
    return np.concatenate(probs)
@torch.no_grad()
def evaluate(model, loader, criterion, device):
    model.eval()
    losses, y_true, y_prob = [], [], []
    for label, line, len_seq in loader:
        x = line.to(device, non_blocking=True)
        t = label.to(device, non_blocking=True)
        lengths = len_seq.to(device, non_blocking=True)
        logits = model(x, None, lengths)
        loss = criterion(logits, t)
        losses.append(float(loss.detach().cpu()))
        y_true.extend(label.cpu().numpy().astype(int).tolist())
        y_prob.extend(torch.sigmoid(logits).detach().cpu().numpy().tolist())
    y_true = np.asarray(y_true).astype(int)
    y_prob = np.asarray(y_prob)
    th, f1 = find_best_threshold(y_true, y_prob)
    return float(np.mean(losses)), f1, th
# Main Training
# Seed ensemble、threshold tuning、final train、submission保存を実施。
# 詳細なハイパーパラメータとモデル本体は公開範囲に合わせて一部非表示。

Lecture1および8以降のHomeworkはコンペ形式ではない?ので割愛。
最終コンペに向けて準備中。