Main Content

メモリ外のシーケンス データを使用したネットワークの学習

この例では、データストアの変換と組み合わせによってメモリ外のシーケンス データで深層学習ネットワークに学習させる方法を説明します。

変換されたデータストアは、基となるデータストアから読み取ったデータを変換または処理します。変換されたデータストアは、深層学習アプリケーションの学習データセット、検証データセット、テスト データセット、および予測データセットのソースとして使用できます。変換されたデータストアを使用して、メモリ外のデータを読み取るか、データのバッチを読み取る際に特定の前処理演算を実行します。予測子とラベルを含む個別のデータストアがある場合、これらのデータストアを組み合わせて深層学習ネットワークにデータを入力できます。

ネットワークの学習時に、入力データのパディング、切り捨て、または分割が行われ、同じ長さのシーケンスのミニバッチが作成されます。メモリ内のデータの場合、関数 trainingOptions に入力シーケンスのパディングと切り捨てを自動的に行うオプションが用意されていますが、メモリ外のデータの場合は、シーケンスのパディングと切り捨てを手動で行わなければなりません。

学習データの読み込み

[1] および [2] に記載のある Japanese Vowels データセットを読み込みます。zip ファイル japaneseVowels.zip には可変長のシーケンスが含まれています。シーケンスは 2 つのフォルダー TrainTest に分割されています。これらのフォルダーには、学習シーケンスとテスト シーケンスがそれぞれ含まれています。これらの各フォルダーでは、シーケンスが 1 から 9 まで番号が付けられたサブフォルダーに分割されています。これらのサブフォルダーの名前はラベル名です。MAT ファイルは各シーケンスを表します。各シーケンスは行列で、行数が 12 (特徴ごとに 1 行) で、列数が可変 (タイム ステップごとに 1 列) です。行数はシーケンス次元で、列数はシーケンス長です。

シーケンス データを解凍します。

filename = "japaneseVowels.zip";
outputFolder = fullfile(tempdir,"japaneseVowels");
unzip(filename,outputFolder);

学習予測子用にファイル データストアを作成し、読み取り関数を関数 load に指定します。関数 load は MAT ファイルから構造体配列にデータを読み込みます。学習フォルダー内のサブフォルダーからファイルを読み取るには、'IncludeSubfolders' オプションを true に設定します。

folderTrain = fullfile(outputFolder,"Train");
fdsPredictorTrain = fileDatastore(folderTrain, ...
    'ReadFcn',@load, ...
    'IncludeSubfolders',true);

データストアをプレビューします。返される struct は、最初のファイルからの単一のシーケンスを含みます。

preview(fdsPredictorTrain)
ans = struct with fields:
    X: [12×20 double]

ラベル用にファイル データストアを作成し、読み取り関数が関数 readLabel (この例の最後に定義) になるように指定します。関数 readLabel は、サブフォルダー名からラベルを抽出します。

classNames = string(1:9);
fdsLabelTrain = fileDatastore(folderTrain, ...
    'ReadFcn',@(filename) readLabel(filename,classNames), ...
    'IncludeSubfolders',true);

データストアをプレビューします。出力は最初のファイルのラベルに対応しています。

preview(fdsLabelTrain)
ans = categorical
     1 

データストアの変換と統合

シーケンス データを予測子のデータストアから深層学習ネットワークに入力するには、シーケンスのミニバッチが同じ長さでなければなりません。シーケンスの長さが 20 になるようにパディングまたは切り捨てを行う関数 padSequence (データストアの最後に定義) を使用して、データストアを変換します。

sequenceLength = 20;
tdsTrain = transform(fdsPredictorTrain,@(data) padSequence(data,sequenceLength));

変換されたデータストアをプレビューします。出力は最初のファイルのパディングされたシーケンスに対応しています。

X = preview(tdsTrain)
X = 1×1 cell array
    {12×20 double}

両方のデータストアの予測子とラベルを深層学習ネットワークに入力するには、関数 combine を使用してこれらを組み合わせます。

cdsTrain = combine(tdsTrain,fdsLabelTrain);

データストアの組み合わせをプレビューします。データストアは 1 行 2 列の cell 配列を返します。最初の要素は予測子に対応しています。2 番目の要素はラベルに対応しています。

preview(cdsTrain)
ans = 1×2 cell array
    {12×20 double}    {[1]}

LSTM ネットワーク アーキテクチャの定義

LSTM ネットワーク アーキテクチャを定義します。入力データの特徴の数を入力サイズとして指定します。100 個の隠れユニットを持つ LSTM 層を指定して、シーケンスの最後の要素を出力します。最後に、出力サイズがクラスの数に等しい全結合層を指定し、その後にソフトマックス層と分類層を配置します。

numFeatures = 12;
numClasses = numel(classNames);
numHiddenUnits = 100;

layers = [ ...
    sequenceInputLayer(numFeatures)
    lstmLayer(numHiddenUnits,'OutputMode','last')
    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer];

学習オプションを指定します。ソルバーを 'adam' に設定し、'GradientThreshold' を 2 に設定します。ミニバッチ サイズを 27、最大エポック数を 75 に設定します。このデータストアはシャッフルをサポートしていないため、'Shuffle''never' に設定します。

ミニバッチが小さく、シーケンスが短いため、学習には CPU が適しています。'ExecutionEnvironment''cpu' に設定します。GPU が利用できる場合、GPU で学習を行うには、'ExecutionEnvironment''auto' (既定値) に設定します。

miniBatchSize = 27;

options = trainingOptions('adam', ...
    'ExecutionEnvironment','cpu', ...
    'MaxEpochs',75, ...
    'MiniBatchSize',miniBatchSize, ...
    'GradientThreshold',2, ...
    'Shuffle','never',...
    'Verbose',0, ...
    'Plots','training-progress');

学習オプションを指定して LSTM ネットワークに学習させます。

net = trainNetwork(cdsTrain,layers,options);

ネットワークのテスト

学習データの場合と同じ手順に従って、ホールドアウトされたテスト データを含む変換されたデータストアを作成します。

folderTest = fullfile(outputFolder,"Test");

fdsPredictorTest = fileDatastore(folderTest, ...
    'ReadFcn',@load, ...
    'IncludeSubfolders',true);
tdsTest = transform(fdsPredictorTest,@(data) padSequence(data,sequenceLength));

学習済みネットワークを使用して、テスト データについて予測を実行します。

YPred = classify(net,tdsTest,'MiniBatchSize',miniBatchSize);

テスト データに対する分類精度を計算します。テスト セットのラベルを取得するには、読み取り関数 readLabel を使用してファイル データストアを作成し、サブフォルダーを含むように指定します。'UniformRead' オプションを true に設定して、出力が垂直に連結されるように指定します。

fdsLabelTest = fileDatastore(folderTest, ...
    'ReadFcn',@(filename) readLabel(filename,classNames), ...
    'IncludeSubfolders',true, ...
    'UniformRead',true);
YTest = readall(fdsLabelTest);
accuracy = mean(YPred == YTest)
accuracy = 0.9351

関数

関数 readLabel は、classNames のカテゴリで指定されたファイル名からラベルを抽出します。

function label = readLabel(filename,classNames)

filepath = fileparts(filename);
[~,label] = fileparts(filepath);

label = categorical(string(label),classNames);

end

関数 padSequence は、シーケンスが指定された長さになるように data.X でシーケンスのパディングと切り捨てを行い、結果を 1 行 1 列の cell で返します。

function sequence = padSequence(data,sequenceLength)

sequence = data.X;
[C,S] = size(sequence);

if S < sequenceLength
    padding = zeros(C,sequenceLength-S);
    sequence = [sequence padding];
else
    sequence = sequence(:,1:sequenceLength);
end

sequence = {sequence};

end

参考

| | | | |

関連するトピック