TensorFlow

TA13 テキスト分類 検討

この記事は約18分で読めます。

TensorFlowを使用してテキスト判定を行ってみました。
(なんとなくの設定が多いです。またデータもかなり簡易なものです。)

ベースとなるtensorFlowのコードは「映画レビューのテキスト分類」になります。
https://www.tensorflow.org/tutorials/keras/text_classification?hl=jahttps://www.tensorflow.org/tutorials/keras/text_classification?hl=ja

対象: CalculiX、OpenFOAMの解析モデルファイル。

学習データCalculiXOpenFOAMのサンプルファイル(インストール時に含まれるもの)

学習モデル作成: TensorFlow 2.9.0

深層学習ライブラリ: keras 2.9.0

判定対象データ:CalculiX、OpenFOAMのサンプルファイル(上記の一部)

条件: 以下のページのファイルを推定します。

CCXのファイル:beam_bar_r1.inp

OpenFoamのファイル:A711_2_sample.zip (controlDictについて)

結果

CCXファイル

check\beam_bar_r1.inp
[0.13862659]

OpenFoamファイル

check\A711_2_sample\system\controlDict
[0.87956655]

ベースにしている映画レビューですが、値が高いほど肯定的で低いほど否定的であることを示しています。今回のデータに照らし合わせると、0寄りがCCXのファイルで1寄りがOpenFoamのファイルになります。ひとまず判断はできているようです。

設定

項目設定内容
学習データ数CCX 964枚
OprnFoam 1665枚
仮想データ
バッチサイズ32
エポック数10

作業

ベースファイルの「ipynb」に合わせてJupyter notebook形式で作業します。

Colaboratoryのサンプルを加工してテキストファイルの分類を行ってみます。
# Colaboratoryのサンプルを加工してテキストファイルの分類を行ってみます。
# CalculiXとOpenFoamのファイル確認
# CalculiXとOpenFoamのファイル群の二つを用いて、二項分類器をトレーニングします。
import matplotlib.pyplot as plt
import os
import re
import shutil
import string
import tensorflow as tf

from tensorflow.keras import layers
from tensorflow.keras import losses
print(tf.__version__)
## 文書フォーマットの分析

もともとは映画レビューの感情分析ですが、解析ファイルのフォーマット違いによる分類へ適用してみます。
### サンプルファイルを収集してセットする

CalculiXとOpenFoamのサンプルファイルを学習用に用意します。
集めたらフォルダに格納します。
#作業に従ったフォルダにします。下記は例。
dataset_dir = 'C:\Work\HP3\\tensorflow\TA13\\files'
os.listdir(dataset_dir)
train_dir = os.path.join(dataset_dir, 'train')
os.listdir(train_dir)
`files\train\ccx` および `files\train\openfoam` ディレクトリには多くのテキストファイルが含まれており、設定ファイルによってフォーマットはまちまちだったりします。
sample_file = os.path.join(train_dir, 'openfoam\\basic\chtMultiRegionFoam\\2DImplicitCyclic\system\controlDict.txt')
with open(sample_file) as f:
  print(f.read())
### データセットを読み込む

次に、データを読み込み、トレーニングに適した形式に準備します。これを行うには、便利な [text_dataset_from_directory](https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/text_dataset_from_directory) ユーティリティを使用します。このユーティリティは、次のようなディレクトリ構造を想定しています。


files/train/
...ccx/
......beamnlptp.dat.txt
......beamnlptp.txt
```
...openfoam/
......combustion/ OpenFoamはサブフォルダがあります。
```
......epsilon1.txt
```
CCXとOpenfoamのファイル拡張子を.txtにします。
単独で機能させるためにimport osを付けています。
CCXとOpenfoamのファイル拡張子を.txtにします。
単独で機能させるためにimport osを付けています。
import os

folder = 'files'

for root, dirs, files in os.walk(folder):
    for filename in files:
        print(os.path.join(root, filename))

        bufOri = filename
        filename, file_extension = os.path.splitext(filename)
        # if file_extension !='.txt':
        try:
            new_file_name = filename + '.txt'
            os.rename(os.path.join(root, bufOri), os.path.join(root, new_file_name))
        except:
            # Handle or ignore the error
            pass
次に、`text_dataset_from_directory` ユーティリティを使用して、ラベル付きの `tf.data.Dataset` を作成します。[tf.data](https://www.tensorflow.org/guide/data) は、データを操作するための強力なツールのコレクションです。

機械学習実験を実行するときは、データセットを[トレーニング]、[検証]、および、[テスト]の 3 つに分割することをお勧めします。

IMDB データセットはすでにトレーニング用とテスト用に分割されていますが、検証セットはありません。以下の `validation_split` 引数を使用して、トレーニングデータの 80:20 分割を使用して検証セットを作成しましょう。

"tf.keras.preprocessing.text_dataset_from_directory"は、TensorFlowのKerasライブラリに含まれる関数で、テキストデータを読み込んでDatasetオブジェクトに変換するために使用されます。この関数は、サブディレクトリがテキストデータのカテゴリ/クラスに対応するように保存されたテキストファイルを読み込むためのものです。この関数は、トレーニングに使用できるDatasetオブジェクトを返します。

この関数は、データの読み込みと処理の方法を制御するための様々なパラメータを使用することができます。これらのパラメータには次のようなものがあります:

directory: テキストファイルが保存されているディレクトリへのパス。

labels: 各テキストファイルに関連付けられたラベル(サブディレクトリ名からラベルへのマッピングを含む辞書)。

batch_size: Dataset内の各バッチに含まれるサンプル数。

shuffle: エポックごとにデータをシャッフルするかどうか。

text_encoding: テキストファイルに使用されるエンコーディング。

全体的に、"tf.keras.preprocessing.text_dataset_from_directory"は、テキストデータの読み込みと前処理を容易にする便利な関数であり、テキストベースの機械学習モデルのトレーニングのプロセスを簡素化することができます。

ChatGPTより
batch_size = 32
seed = 42

raw_train_ds = tf.keras.utils.text_dataset_from_directory(
    'files/train', 
    batch_size=batch_size, 
    validation_split=0.2, 
    subset='training', 
    seed=seed)
上記のように、トレーニングフォルダには 2629 の例があり、そのうち 80% (2104) をトレーニングに使用します。以下に示すとおり、データセットを `model.fit` に直接渡すことで、モデルをトレーニングできます。`tf.data` を初めて使用する場合は、データセットを繰り返し処理して、次のようにいくつかの例を出力することもできます。
for text_batch, label_batch in raw_train_ds.take(1):
  for i in range(3):
    print("Review", text_batch.numpy()[i])
    print("Label", label_batch.numpy()[i])
ラベルは 0 または 1 です。これらのどれがCCXかOpenFoamのファイルであるかを確認するには、データセットの `class_names` プロパティを確認できます。
print("Label 0 corresponds to", raw_train_ds.class_names[0])
print("Label 1 corresponds to", raw_train_ds.class_names[1])
次に、検証およびテスト用データセットを作成します。トレーニング用セットの残りの 525 ファイルを検証に使用します。
raw_val_ds = tf.keras.utils.text_dataset_from_directory(
    'files/train', 
    batch_size=batch_size, 
    validation_split=0.2, 
    subset='validation', 
    seed=seed)
raw_test_ds = tf.keras.utils.text_dataset_from_directory(
    'files/test', 
    batch_size=batch_size)
### トレーニング用データを準備する

次に、便利な `tf.keras.layers.TextVectorization` レイヤーを使用して、データを標準化、トークン化、およびベクトル化します。
def custom_standardization(input_data):
  lowercase = tf.strings.lower(input_data)
  stripped_html = tf.strings.regex_replace(lowercase, '<br />', ' ')
  return tf.strings.regex_replace(stripped_html,
                                  '[%s]' % re.escape(string.punctuation),
                                  '')
max_features = 10000
sequence_length = 250

vectorize_layer = layers.TextVectorization(
    standardize=custom_standardization,
    max_tokens=max_features,
    output_mode='int',
    output_sequence_length=sequence_length)
# Make a text-only dataset (without labels), then call adapt
train_text = raw_train_ds.map(lambda x, y: x)
vectorize_layer.adapt(train_text)
def vectorize_text(text, label):
  text = tf.expand_dims(text, -1)
  return vectorize_layer(text), label
# retrieve a batch (of 32 reviews and labels) from the dataset
text_batch, label_batch = next(iter(raw_train_ds))
first_review, first_label = text_batch[0], label_batch[0]
print("Review", first_review)
print("Label", raw_train_ds.class_names[first_label])
print("Vectorized review", vectorize_text(first_review, first_label))
print("1287 ---> ",vectorize_layer.get_vocabulary()[1287])
print(" 313 ---> ",vectorize_layer.get_vocabulary()[313])
print('Vocabulary size: {}'.format(len(vectorize_layer.get_vocabulary())))
モデルをトレーニングする準備がほぼ整いました。最後の前処理ステップとして、トレーニング、検証、およびデータセットのテストのために前に作成した TextVectorization レイヤーを適用します。
train_ds = raw_train_ds.map(vectorize_text)
val_ds = raw_val_ds.map(vectorize_text)
test_ds = raw_test_ds.map(vectorize_text)
### パフォーマンスのためにデータセットを構成する

以下は、I/O がブロックされないようにするためにデータを読み込むときに使用する必要がある 2 つの重要な方法です。

`.cache()` はデータをディスクから読み込んだ後、データをメモリに保持します。これにより、モデルのトレーニング中にデータセットがボトルネックになることを回避できます。データセットが大きすぎてメモリに収まらない場合は、この方法を使用して、パフォーマンスの高いオンディスクキャッシュを作成することもできます。これは、多くの小さなファイルを読み込むより効率的です。

`.prefetch()` はトレーニング中にデータの前処理とモデルの実行をオーバーラップさせます。
AUTOTUNE = tf.data.AUTOTUNE

train_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
test_ds = test_ds.cache().prefetch(buffer_size=AUTOTUNE)
### モデルを作成する

ニューラルネットワークを作成します。
embedding_dim = 16
model = tf.keras.Sequential([
  layers.Embedding(max_features + 1, embedding_dim),
  layers.Dropout(0.2),
  layers.GlobalAveragePooling1D(),
  layers.Dropout(0.2),
  layers.Dense(1)])

model.summary()
### 損失関数とオプティマイザ
model.compile(loss=losses.BinaryCrossentropy(from_logits=True),
              optimizer='adam',
              metrics=tf.metrics.BinaryAccuracy(threshold=0.0))
### モデルをトレーニングする

`dataset` オブジェクトを fit メソッドに渡すことにより、モデルをトレーニングします。
epochs = 10
history = model.fit(
    train_ds,
    validation_data=val_ds,
    epochs=epochs)
### モデルを評価する

モデルがどのように実行するか見てみましょう。2 つの値が返されます。損失(誤差、値が低いほど良)と正確度です。
loss, accuracy = model.evaluate(test_ds)

print("Loss: ", loss)
print("Accuracy: ", accuracy)
トレーニングと検証中に監視されている各メトリックに対して 1 つずつ、計 4 つのエントリがあります。このエントリを使用して、トレーニングと検証の損失とトレーニングと検証の正解度を比較したグラフを作成することができます。
acc = history_dict['binary_accuracy']
val_acc = history_dict['val_binary_accuracy']
loss = history_dict['loss']
val_loss = history_dict['val_loss']

epochs = range(1, len(acc) + 1)

# "bo" is for "blue dot"
plt.plot(epochs, loss, 'bo', label='Training loss')
# b is for "solid blue line"
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.show()
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend(loc='lower right')

plt.show()
このグラフでは、点はトレーニングの損失と正解度を表し、実線は検証の損失と正解度を表します。


特定のケースでは、検証の正解度が向上しなくなったときにトレーニングを停止することにより、過適合を防ぐことができます。これを行うには、`tf.keras.callbacks.EarlyStopping` コールバックを使用することができます。
## モデルをエクスポートする

上記のコードでは、モデルにテキストをフィードする前に、`TextVectorization` レイヤーをデータセットに適用しました。モデルで生の文字列を処理できるようにする場合 (たとえば、展開を簡素化するため)、モデル内に `TextVectorization` レイヤーを含めることができます。これを行うには、トレーニングしたばかりの重みを使用して新しいモデルを作成します。
export_model = tf.keras.Sequential([
  vectorize_layer,
  model,
  layers.Activation('sigmoid')
])

export_model.compile(
    loss=losses.BinaryCrossentropy(from_logits=False), optimizer="adam", metrics=['accuracy']
)

# Test it with `raw_test_ds`, which yields raw strings
loss, accuracy = export_model.evaluate(raw_test_ds)
print(accuracy)
### 新しいデータの推論

新しい例の予測を取得するには、`model.predict()`を呼び出します。
# checkFile = 'check\\beam_bar_r1.inp'
checkFile = 'check\A711_2_sample\system\controlDict'

with open(checkFile, 'r') as file:
    content = file.read()
    # print(content)

examples = [
content
]

export_model.predict(examples)
buf1= export_model.predict(examples)

print(checkFile)
print(buf1[0])

サンプルファイルTA13_text_classification.ipynb

コメント

Translate »
タイトルとURLをコピーしました