konchangakita

KPSを一番楽しんでいたブログ 会社の看板を背負いません 転載はご自由にどうぞ

【DeepLearning特訓】RNN応用 LSTM編

E資格向けの自習アウトプット
自分用メモ

LSTM:Long Short-Term Memory(長短期記憶)は、RNNで系列が長くなっていった時におきてしまう「長期依存性の課題」への解決アプローチの一つです

長期依存性の課題

RNNの弱点として多くの時間ステップでわたって伝播されて勾配が消失してしまう「勾配消失問題」があります。

【課題解決アプローチ方法】
スキップ接続:時刻をスキップして直接続、粗い時間スケールを得る
Leakyユニット:前の時刻から接続をα倍、現時刻の入力(1-α)倍する
接続の削除
LSTM:ゲート付きRNN
GRU

LSTM の手法

内部状態という考え方を新しく付与
f:id:konchangakita:20210130113536p:plain:w300

内部状態に影響を与えるj3つ のゲートを導入して、勾配消失問題に対応
忘却ゲート(f):前の状態の影響率
入力ゲート(i):現時刻の入力データの影響率
出力ゲート(o):現在の状態の影響率



LSTM 順伝播の構造

各ゲートを追加してイメージはこんな感じ
かなりややこしくなってきた
f:id:konchangakita:20210130124147p:plain
f:id:konchangakita:20210130001813p:plain:w400


整理のためにも順伝播までを Pythonコードの実装

# シグモイド
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# LSTMモデル
# N:バッチサイズ、D:入力単語数、H:中間層の出力次元数
class LSTM:
    def __init__(self, wx, wh, b):
        self.params = [wx, wh, b]   # wx[D,4H], wh[H,4H], b[4H]
        self.grads = [np.zeros_like(wx), np.zeros_like(wh), np.zeros_like(b)]
        self.cache = None
    
    def forward(self, x, h_prev, c_prev):
        wx, wh, b = self.params 
        N, H = h_prev.shape

        A = np.dot(h_prev, wh) + np.dot(x, wx) + b  # [N,4H]

        # slice
        f = sigmoid(A[:, :H])       # 忘却ゲート [N,H]
        i = sigmoid(A[:, 2*H:3*H])  # 入力ゲート [N,H]
        g = np.tanh(A[:, H:2*H])  
        o = sigmoid(A[:, 3*H:])     # 出力ゲート [N,H]

        c_next = f * c_prev + i * g # 現時刻の状態 [N,H]
        h_next = o * np.tanh(c_next) # 現時刻の出力 [N,H]

        self.cache = (x, h_prev, c_prev, f, i, g, o, c_next)
        return h_next, c_next



適当な入力値で実行してみる

import numpy as np

# 入力を適当に定義
x = np.arange(25).reshape(5,5)
h_prev = np.ones((5,10))
c_prev = np.zeros((5,10))

# 重みを初期化
wx = np.random.randn(5, 40)
wh = np.random.randn(10, 40)
b = np.zeros(40)

# モデルインスタンス
lstm = LSTM(wx, wh, b)

# 順伝播
lstm.forward(x, h_prev, c_prev)


Peephole Connections

前の内部状態が各ゲートに影響与えるコネクションを追加
f:id:konchangakita:20210130124306p:plain
f:id:konchangakita:20210130013304p:plain:w480


さいごに

ここからが自然言語処理の本番だ
実践で使えるRNN応用技術にとりくんでいく

【DeepLearning特訓】RNNモデルの考え方

E資格向けの自習アウトプット
自分用メモ

RNN を利用したモデル構築の考慮事項について
E資格試験対策の意味合いが多し

RNN の学習方法

通時的誤差逆伝播(BPTT: Back Propagation Though Time)

Simple RNNの逆伝播は1つ先の時刻の勾配を含んで計算されていたので、並列で処理できない
つまりメモリコストも大きくなる
中間層同士の接続なので強力ではある

教師強制

訓練時に、前の時刻の正解ラベルを中間層へ入力として与える
並列処理が可能になるが、出力層が必要な情報を全てもっていることは少ないので強力ではない
前日の終値が確実に分かっている、株価とかでは使える


出力回帰(出力層から中間層へ接続)は、RNNほど強力ではない

教師強制で学習できる

有向グラフィカルモデル

求めたいものが出力値の確率であるとき、RNNのモデルは有向グラフィカルモデルといえる
こんなイメージ
f:id:konchangakita:20210127100739p:plain

RNNを使った「文脈で条件付けされた」系列モデリング

言葉としてややこしいが、文脈=「過去の真の値」と考える
直前の真の値が入力として中間層へ接続される
株価予想もそう(過去の終値が今日には確定している)

深層回帰結合型ネットワーク

RNN の層を深くする方法
 ・隠れた回帰状態 ➔ 階層別の回帰に分解
 ・より深い計算 ➔ 中間層でより深い接続
 ・経路が長くなる ➔ スキップ接続で緩和

再帰ニューラルネットワーク

RNN のもう一つの一般系と呼ばれている
木構造として扱う、深さを大幅に減らし長期依存を取り扱うのに有利になる可能性がある
最適な木構造をどのように構築するかは未解決の課題

エコーステートネットワーク

RNNで難しい一つ前の時刻からの重み𝑊_ℎ,"現時刻の入力重み" 𝑊_𝑥の学習が難しい
スペクトル半径を3などに固定し、単純な重みに固定する戦略

双方向RNN

出力が入力系列全体に依存していることがある
音声認識:後ろに続く音素によって、直前の音素が決定する
翻訳:言語によって語順が変わってくる

系列全体を参照できる仕組みが必要
逆方向に接続するRNNを追加し、結果をマージ
f:id:konchangakita:20210127101754p:plain

さいごに

このあたりの考え方は実際にコード組んでみないことには、習得するのが難しそう

【DeepLearning特訓】RNN 入門

E資格向けの自習アウトプット
自分用メモ

RNN(Recurrent Neural Network)回帰結合型ニューラルネットワークは、時系列データを処理するためのニューラルネットワークCNNが格子状のデータを処理するのに特化RNNは系列上の値 𝑥^*1,𝑥^*2,,,,,𝑥^*3 を処理するのに特化、可変長な系列データにも対応

応用例

機械翻訳Google翻訳など
音声認識スマホとかスマートスピーカー
CNNと組み合わせて画像からキャプションを生成

RNN モデル概要

前の時刻の中間層の出力を次の中間層へ渡す
時刻𝑡 の入力データ 𝑥^*4 とすると
(RNNでは縦に描いて横に並べていくことが多くなる)
f:id:konchangakita:20210125215003p:plain

RNN の中間層の構造

中間層での計算を表すと
f:id:konchangakita:20210125215216p:plain
計算グラフでそれぞれの要素を書き下してみる
f:id:konchangakita:20210125215240p:plain

RNN の順伝播

各時刻ごとにAffine変換と損失関数の計算を行って完成
一つ前の時刻の中間層の出力と、この時刻の入力を合わせて計算し
中間層での出力を次の時刻の中間層へ渡す
f:id:konchangakita:20210125215519p:plain
f:id:konchangakita:20210129004055p:plain

RNN の逆伝播

勾配の計算には一つ先の時刻の勾配を受け取って含めて計算し、
一つ前の時刻へ勾配計算結果を渡す
f:id:konchangakita:20210125215731p:plain
f:id:konchangakita:20210125215822p:plain

Python コードで理解してみた方が分かりやすいかも
f:id:konchangakita:20210125220249p:plain

さいごに

RNN(回帰結合型ネットワーク)からどんどんややこしくなってきました
ディープラーニングにおける時系列の考え方は自然言語処理にはかかせない要素
もう少し、RNNの基礎をつづく

*1:0

*2:1

*3:𝑡

*4:𝑡

【DeepLearning特訓】CNN 進化の歴史

E資格向けの自習アウトプット
自分用メモ

CNN発展の歴史を抑えておく
ILSVRC(ImageNet Large Scale Visual Recognition Challenge):画像認識コンペ
で 2012年の トロント大 ヒントン教授の率いるチームが CNN を採用したAlexNetで圧倒的な成績をのしてディープラーニングの火付け役となったと言われています

2012年以降のILSVRCの優勝アーキテクチャと有名どころ

AlexNet(2012) 8層
ZFNet(2013) 8層
GoogleNet(2014) 22層:Inception Moduleで並列化、Auxiliary Loss, Global Average Pooling, Pointwise Convolution
VGG(2014) :深いネットワーク構造が特徴、構造が単純なので応用しやすい
ResNet(2015) 152層:Residual Blockのショートカット構造
DenseNet(2016):Dense Blockで層の出力をショートカット伝搬する、Transition層でダウンサンプリング
SENet(2017) 152層

LeNet

1998年(!?)現Facebook AI ResearchのYann LeCun氏による CNN の元祖
畳み込み、プーリングなどのアーキテクチャ実装済
活性化関数がシグモイドであることやプーリングがMAXではなくサブサンプリングなのが違い

R-CNN(2013)

Regions with CNN(領域CNN)
Selective Searchで物体がありそうなところにあたりを付けて(Region Proposal)、SVMで分類
CNNは特徴抽出のみなので、分類部分は学習できない
問題点
 ・複数のモデル個別で学習が必要
 ・あたりをつけた候補領域の数だけCNNを回すので、実行時間がかかる
 ・何もない領域にあたりをつけた時の大きく間違ってしまう

ざっくりこんなイメージ
f:id:konchangakita:20210123133213p:plain

Fast R-CNN (2015)

R-CNN の改良版
候補領域の数の分だけ CNN 回していたのを、まず画像全体に CNN 畳み込んで特徴量マップを抽出し、候補領域で切り抜いた画像部分を特徴量マップを抽出(ROI Pooling)
CNNは一回だけになるので、速くなる

ざっくりこんなイメージ
f:id:konchangakita:20210123133244p:plain

Faster R-CNN(2015)

Fast R-CNN を更に改良
Fast R-CNN で時間がかかっていたのはほぼ Selective Search で候補領域を指定いいた部分
Selective Search に CNNの特徴マップを使用して物体検知(Regional Proposal Network)
候補領域抽出タスクと分類タスクで損失関数を共有(Multi Task Loss )し End-to-End で学習を実現

ざっくりこんなイメージ
f:id:konchangakita:20210123123421p:plain

YOLO(2016)

You Only Look Once(You Only Live Onceからもじった)
画像全体をグリッド分割し、各グリッドに対して分類・矩形指定タスクを行う
信頼度スコアを利用して、高速でリアルタイムで物体の「検出」と「識別」を行う

ざっくりこんなイメージ?
f:id:konchangakita:20210123135749p:plain


とりあえず

CNNに関連する有名どころだけをピックアップ
一旦 CNNを卒業して、自然言語処理へと勉強すすめる

【DeepLearning特訓】CNN を TensorFlow で実装

E資格向けの自習アウトプット
自分用メモ

TensorFlow は、Googleさんが公開している機械学習で便利なライブラリ
現在のところPython では、PyTorch と2大巨頭って感じ?今まで PyTorch 使いなれてきましたが、KPS 的に TensorFlow 使いこなせるようになったほうがよさげなので、この度初挑戦

余談ですが、「テンサー」か「テンソル」かは、Googleの中の人もどっちも使うって言ってた(ようするにどっちでもおk)
なんとなく、ちゃんと学問として線形代数とかやってた人はテンソル派な気がする(なんか頭よさそー)

TensorFlow でモデルを作る下準備

まずは開発環境のバージョンを確認

import sys
import tensorflow as tf
続きを読む

【DeepLearning特訓】CNN 実装のポイント

E資格向けの自習アウトプット
自分用メモ

CNN実装するには、Pythonでの計算する行列のカタチを意識してやるのが重要です
その基本的なテクニックについて
E資格的には numpy での実装方法が聞かれるのかな

画像の読み込みと確認方法

まずは基本中の基本で画像を一枚読み込んで、チャネルごとのイメージを掴んで見る
Pillow で画像の読み込んで、numpy array でチャネルごとの成分を「0」にして RGB の画像を確認する

import matplotlib.pyplot as plt
from PIL import Image
from io import BytesIO
import numpy as np

filename = 'dataset/FF14.jpg'
img = Image.open(filename)
img_array = np.asarray(img)  # (H, W, Ch)

def get_channel(image,channel='r'):
    # イメージをコピー
    new_image = image.copy()
    if channel=='r':
        # 「r」が指定された場合、「g」「b」は0にする
        new_image[:,:,1] = 0
        new_image[:,:,2] = 0
    elif channel=='g':
         # 「g」が指定された場合、「r」「b」は0にする
        new_image[:,:,0] = 0
        new_image[:,:,2] = 0
    elif channel=='b':
         # 「g」が指定された場合、「r」「b」は0にする
        new_image[:,:,0] = 0
        new_image[:,:,1] = 0
    return new_image


print("REDチャンネル")
image_2 = get_channel(img_array,channel='r')
plt.imshow( image_2 )
plt.axis("off")
plt.show()

print("GREENチャンネル")
image_2 = get_channel(img_array,channel='g')
plt.imshow( image_2 )
plt.axis("off")
plt.show()

print("BLUEチャンネル")
image_2 = get_channel(img_array,channel='b')
plt.imshow( image_2 )
plt.axis("off")
plt.show()


f:id:konchangakita:20210115095904p:plain

画像を計算しやすい行列に変換

入力される画像データは4次元(画像枚数 N, チャネル数 Ch, H, W)ではいってきて、カーネル(フィルタ)で局所的な演算をするわけなので、そのまんまでは扱いにくい
f:id:konchangakita:20210114235653p:plain


畳み込み処理(カーネルサイズ、ストライプ数)、プーリングの設定に合わせて、行列を組み直してからカーネルとの計算をおこなうと具合がよい
f:id:konchangakita:20210115005918p:plain
(行 x 列だとの計算しやすい)


Numpy だけで行うとこの実装が結構ややこしくて、確認が何度も必要だったりするので実装が結構大変だが、PyTorch や TensorFlow では簡単に実装できる関数が用意されていたりする

PyTorch は過去にトライしたりもしている
PyTorchを使ったDeep Learningのお勉強 画像認識編(CIFAR-10) - konchangakita

畳み込みを効率よくするには

畳み込みネットワークは特徴量の学習コストが高い

計算コストを減らすための工夫
 ・ランダムなカーネルを利用
 ・層ごとの貪欲事前学習(問題を分割し、要素ごとに最適化)
 ・教師なし学習の利用


さいごに

このあたりは試験対策の為に、考え方が重要なので理解しておく
実装は PyTorch はすでに挑戦したので、TensorFlow での実装をおこなってみようかな

【DeepLearning特訓】CNN入門

E資格向けの自習アウトプット
自分用メモ

CNN(Convolutional Neural Network)は、畳み込みニューラルネットワークと呼ばれる、畳み込みという圧縮に似た(圧縮ではない)処理で入力次元を削減しつつ、特徴量をあぶり出していく手法です
主に画像のクラス分類や物体検出、領域分割(セグメンテーション)などに使われることが多い模様

CNNの概念

画像データは、ちょっとした解像度のデータでも入力データとしては非常に大きい次元になる。チャネル数 x H x W (カラーだとRGB 3チャネル)
ちょっとしたスマホのカメラでも何万画素になるので、各層のパラメータもすごくでかくなりがち
また画像は人間の目からすると、見た目は変わらない1ピクセルずらしたただけでも入力データとしては、全く別物と扱われてしまう
これを改善する処理が 畳み込み(Convolution)プーリング(Pooling)
近い位置の情報も統合して圧縮したりするので、少しの移動にも強い

処理の流れは以下な感じ
f:id:konchangakita:20210113192830p:plain

畳み込み

画像データは3次元(チャネル数 x H x W )の形状であり、空間的に近いピクセルは似たような値であったり、逆にとおいピクセルは同士は関わりが薄かったり、RGBそれぞれは関連性があったりとその形状に特徴がある
畳み込み層は、この3次元の形状は維持しながら、カーネル(フィルタ)を使って特徴量をあぶり出してゆく

やってることは、画像のフィルター処理のようなもの
カーネル(フィルタ)をずらしながら積和演算を繰り返していく
f:id:konchangakita:20210113202414p:plain
重みとバイアスは学習パラメータ

学習パラメータであるカーネル(フィルタ)が共有され使いまわしできるので、メモリの使用量が減る

重要な設定項目

パディング:隅っこのピクセルは使われる回数が少なくなるので、周りゼロ埋めする
f:id:konchangakita:20210113223855p:plain

numpyでは、np.pad を使うだけ

gazo = np.arange(9).reshape(3,3)
np.pad(gazo, 1, 'constant')

===
array([[0, 0, 0, 0, 0],
       [0, 0, 1, 2, 0],
       [0, 3, 4, 5, 0],
       [0, 6, 7, 8, 0],
       [0, 0, 0, 0, 0]])

ストライド:1度のフィルタ計算をどれだけずらすか
f:id:konchangakita:20210114124854p:plain
f:id:konchangakita:20210114124948p:plain

プーリング

局所的な領域から重要は特徴のみを抽出する
学習パラメータを持たず、実装はシンプルだが強力
小さな移動があっても同じ結果を返してくれる

最大値プーリング、カーネル内の最大値を一つ返す
平均値プーリング、カーネル内での平均値を返す
f:id:konchangakita:20210113234753p:plain


まとめ

画像処理は IoT でも需要なので、熱心にお勉強中
試験でもここはパーフェクトしたい
この後は、Python実装のためのお作法をおさえていきます