ツンからデレに変換する 簡易LM を作ってみた!
📅 更新履歴
- 2025/12/24: 初投稿
1. はじめに
はじめまして、Daichi と申します。
今年の4月ごろから、自分だけのAIを作りたいな~と思い、趣味でAIの勉強をしています。
学びの記録は、基本的に LinkedIn にアウトプットしてます。
2. 背景
現在、LM (Transformer) に挑戦しており、
仕組みを理解するために、手元で動く最小構成の簡易LMが必要になりました。
そこで、PyTorch を用いて開発することにしました。
題材として単純な翻訳ではなく、
ツン文から、デレ文へ変換できたら面白いなと思い、作ってみました。
3. 概要
論文[1] を参考にしつつ、Encoder + Decoder 構成で実装し、
推論時に同じ出力に固定されすぎないよう Top-p Sampling を採用しました。
モデル名は、「Dere + Transformer」から Dereformer としました。
-
何ができるのか
- ツン文から、デレ文に変換
-
技術スタック
- Python (3.12)
- PyTorch (2.9.1)
4. デモ
Input: 急に電話してくんな💢
Output: でも、声聞けるとちょっと安心する🥺

うまくできなかった例
Input: 調子乗んなよバカ💢
Run1: それくらい自信持ってくれてくれてた方が、あたしい🥰
Run2: それくらい自信持ってくれてくれてくれてくれてた方が、あたしも嬉しい🥰

メモ:学習データ量が少ない影響で、同じフレーズの繰り返しが出やすいと考えられる。
5. 詳細
5.1. 学習について
- 環境:CPU
- 時間:約1.5時間 (1100 Epochs)
5.2. データセットについて
- 220個
- 「1ペア = input 1文 + output 1文」を110個用意
-
こんな感じのを LLMに作ってもらいました
tsun2dere.json[ { "input": "べ、別にあんたのことなんか😠", "output": "あんたのこと好きに決まってんだろ🥰" }, { "input": "う、うるさいなっ!💢", "output": "あんたの声、ちょっと落ち着く🥰" } ]
-
- 「1ペア = input 1文 + output 1文」を110個用意
5.3. ハイパラメータについて
-
d_model = 128(次元数) -
nhead = 4(Head 数) -
num_layers = 1(Encoder、 Decoderのレイヤー数)
5.4. Tokenizer について
学習用のデータセットに含まれる文字を、
語彙リストに登録する形とし、自作しました。(1文字:1トークンID)
6. 概要図
開く

7. 開発で苦労したこと
7.1. dimの考え方
PyTorch は今まで触ったことがなく、dim の概念の理解に苦労しました。
そこで、tensor 情報を表示する関数を作り、色々試して理解していきました。
def inspect_tensor
# -*- coding:utf-8 -*-
import torch
def inspect_tensor(x, verbose=None) -> torch.Tensor:
if not isinstance(x, torch.Tensor):
x = torch.tensor(x)
print("🔍 Tensor Structure")
print(f" 🧱 shape: {x.shape}")
print(f" 📐 dims : {x.dim()} --> {[f'dim:{d}' for d in range(x.dim())]}")
for dim, size in enumerate(x.shape):
print(f" 🔷 [dim:{dim}]: {size}")
if verbose is not None:
print(f" 📘 Details:")
_inspect_tensor(x, first_indent_size=6, verbose=verbose)
return x
def _inspect_tensor(x, first_indent_size, verbose) -> None:
# Indent settings
first_indent = ' ' * first_indent_size
indent = ' ' * 2
# Verbose handling
if verbose < 0:
# Display all dimensions
break_dim = x.dim() if x.dim() > 0 else 1
else:
# Display up to and including dim=verbose (0-based index)
break_dim = verbose + 1
# Define a recursive function
def _recursive(tensor, dim=0):
# Nothing if the dimension equals the breaking dimension
if dim == break_dim:
return
# Scalar
elif tensor.dim() == 0:
print(f"{first_indent + indent * dim}[] -> {tensor.item()}")
return
else:
for i in range(tensor.size(0)):
print(f"{first_indent + indent * dim}[dim:{dim}] index:{i} -> ", end='')
# Feature
if tensor.dim() == 1:
print(f"{tensor[i].item()}")
# Matrix
else:
print(f"{tensor[i].detach().cpu().numpy().tolist()}")
_recursive(tensor[i], dim=dim+1)
# Execute the inner function
_recursive(x)
x = inspect_tensor(
[
# [dim: 0] -- index: 0
[1, 2, 3], # [dim: 1] -- indexes: 0, 1, 2
# [dim: 0] -- index: 1
[4, 5, 6] # [dim: 1] -- indexes: 0, 1, 2
],
verbose=-1
)
print(x)
output (sample01.py)
🔍 Tensor Structure
🧱 shape: torch.Size([2, 3])
📐 dims : 2 --> ['dim:0', 'dim:1']
🔷 [dim:0]: 2
🔷 [dim:1]: 3
📘 Details:
[dim:0] index:0 -> [1, 2, 3]
[dim:1] index:0 -> 1
[dim:1] index:1 -> 2
[dim:1] index:2 -> 3
[dim:0] index:1 -> [4, 5, 6]
[dim:1] index:0 -> 4
[dim:1] index:1 -> 5
[dim:1] index:2 -> 6
tensor([[1, 2, 3],
[4, 5, 6]])
x = torch.tensor([1, 2, 3])
print(x)
inspect_tensor(x, verbose=-1)
print()
x = x.unsqueeze(0)
print(x)
inspect_tensor(x, verbose=-1)
output (sample02.py)
tensor([1, 2, 3])
🔍 Tensor Structure
🧱 shape: torch.Size([3])
📐 dims : 1 --> ['dim:0']
🔷 [dim:0]: 3
📘 Details:
[dim:0] index:0 -> 1
[dim:0] index:1 -> 2
[dim:0] index:2 -> 3
tensor([[1, 2, 3]])
🔍 Tensor Structure
🧱 shape: torch.Size([1, 3])
📐 dims : 2 --> ['dim:0', 'dim:1']
🔷 [dim:0]: 1
🔷 [dim:1]: 3
📘 Details:
[dim:0] index:0 -> [1, 2, 3]
[dim:1] index:0 -> 1
[dim:1] index:1 -> 2
[dim:1] index:2 -> 3
7.2. batch_first の扱い
TransformerEncoderLayer などでは
引数に batch_first の設定項目があり、
それに合った shape を input として渡す必要があります。
違いについて
例えば、以下の2文をバッチとして考えてみます。
- "I" "like" "you"
- "He" "is" "kind"
-
batch_first=Falseの場合:-
[dim0, dim1]=[seq_len, batch_size]
👉 縦に流れる感じ (時間方向)イメージ# shape: [3, 2] [ ["I", "He"], ["like", "is"], ["you", "kind"] ]
-
-
batch_first=Trueの場合-
[dim0, dim1]=[batch_size, seq_len]
👉 横に並べる感じ (普通のデータ表記に近い形)イメージ# shape: [2, 3] [ ["I", "like", "you"], ["He", "is", "kind"] ]
-
8. 終わりに
最後まで読んでくださりありがとうございました🙇♂️
以前「個人でAIを作るのは無理だろう」と言われたことがあったのですが、
ひとまず形にできたため、自分を信じてよかったと思ってます。
日々 少しずつ学んで積み上げていけば、時間はかかるが不可能ではないと感じています。
また、学んでる中で新しいAIの構想も思いついたため、
現在は論文の執筆にも着手しています。
Discussion