Trang này được dịch bởi Cloud Translation API.
Switch to English

Tải văn bản

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải xuống sổ tay

Hướng dẫn này trình bày hai cách để tải và xử lý trước văn bản.

  • Đầu tiên, bạn sẽ sử dụng các tiện ích và lớp của Keras. Nếu bạn chưa quen với TensorFlow, bạn nên bắt đầu với những thứ này.

  • Tiếp theo, bạn sẽ sử dụng các tiện ích cấp thấp hơn như tf.data.TextLineDataset để tải các tệp văn bản và tf.text để xử lý trước dữ liệu để kiểm soát chi tiết hơn.

import collections
import pathlib
import re
import string

import tensorflow as tf

from tensorflow.keras import layers
from tensorflow.keras import losses
from tensorflow.keras import preprocessing
from tensorflow.keras import utils
from tensorflow.keras.layers.experimental.preprocessing import TextVectorization

import tensorflow_datasets as tfds
pip install tensorflow-text
Collecting tensorflow-text
[?25l  Downloading https://files.pythonhosted.org/packages/28/b2/2dbd90b93913afd07e6101b8b84327c401c394e60141c1e98590038060b3/tensorflow_text-2.3.0-cp36-cp36m-manylinux1_x86_64.whl (2.6MB)
[K     |████████████████████████████████| 2.6MB 2.9MB/s 
[?25hRequirement already satisfied: tensorflow<2.4,>=2.3.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow-text) (2.3.0)
Requirement already satisfied: numpy<1.19.0,>=1.16.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (1.18.5)
Requirement already satisfied: keras-preprocessing<1.2,>=1.1.1 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (1.1.2)
Requirement already satisfied: scipy==1.4.1 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (1.4.1)
Requirement already satisfied: tensorboard<3,>=2.3.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (2.3.0)
Requirement already satisfied: h5py<2.11.0,>=2.10.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (2.10.0)
Requirement already satisfied: google-pasta>=0.1.8 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (0.2.0)
Requirement already satisfied: astunparse==1.6.3 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (1.6.3)
Requirement already satisfied: six>=1.12.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (1.15.0)
Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (0.35.1)
Requirement already satisfied: wrapt>=1.11.1 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (1.12.1)
Requirement already satisfied: grpcio>=1.8.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (1.32.0)
Requirement already satisfied: opt-einsum>=2.3.2 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (3.3.0)
Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (1.1.0)
Requirement already satisfied: absl-py>=0.7.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (0.10.0)
Requirement already satisfied: protobuf>=3.9.2 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (3.12.4)
Requirement already satisfied: gast==0.3.3 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (0.3.3)
Requirement already satisfied: tensorflow-estimator<2.4.0,>=2.3.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow<2.4,>=2.3.0->tensorflow-text) (2.3.0)
Requirement already satisfied: google-auth<2,>=1.6.3 in /usr/local/lib/python3.6/dist-packages (from tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (1.17.2)
Requirement already satisfied: werkzeug>=0.11.15 in /usr/local/lib/python3.6/dist-packages (from tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (1.0.1)
Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.6/dist-packages (from tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (3.3.2)
Requirement already satisfied: setuptools>=41.0.0 in /usr/local/lib/python3.6/dist-packages (from tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (50.3.0)
Requirement already satisfied: requests<3,>=2.21.0 in /usr/local/lib/python3.6/dist-packages (from tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (2.23.0)
Requirement already satisfied: tensorboard-plugin-wit>=1.6.0 in /usr/local/lib/python3.6/dist-packages (from tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (1.7.0)
Requirement already satisfied: google-auth-oauthlib<0.5,>=0.4.1 in /usr/local/lib/python3.6/dist-packages (from tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (0.4.1)
Requirement already satisfied: pyasn1-modules>=0.2.1 in /usr/local/lib/python3.6/dist-packages (from google-auth<2,>=1.6.3->tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (0.2.8)
Requirement already satisfied: cachetools<5.0,>=2.0.0 in /usr/local/lib/python3.6/dist-packages (from google-auth<2,>=1.6.3->tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (4.1.1)
Requirement already satisfied: rsa<5,>=3.1.4; python_version >= "3" in /usr/local/lib/python3.6/dist-packages (from google-auth<2,>=1.6.3->tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (4.6)
Requirement already satisfied: importlib-metadata; python_version < "3.8" in /usr/local/lib/python3.6/dist-packages (from markdown>=2.6.8->tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (2.0.0)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/dist-packages (from requests<3,>=2.21.0->tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (2020.6.20)
Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from requests<3,>=2.21.0->tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (3.0.4)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.6/dist-packages (from requests<3,>=2.21.0->tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (1.24.3)
Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.6/dist-packages (from requests<3,>=2.21.0->tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (2.10)
Requirement already satisfied: requests-oauthlib>=0.7.0 in /usr/local/lib/python3.6/dist-packages (from google-auth-oauthlib<0.5,>=0.4.1->tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (1.3.0)
Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in /usr/local/lib/python3.6/dist-packages (from pyasn1-modules>=0.2.1->google-auth<2,>=1.6.3->tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (0.4.8)
Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.6/dist-packages (from importlib-metadata; python_version < "3.8"->markdown>=2.6.8->tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (3.3.1)
Requirement already satisfied: oauthlib>=3.0.0 in /usr/local/lib/python3.6/dist-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib<0.5,>=0.4.1->tensorboard<3,>=2.3.0->tensorflow<2.4,>=2.3.0->tensorflow-text) (3.1.0)
Installing collected packages: tensorflow-text
Successfully installed tensorflow-text-2.3.0

import tensorflow_text as tf_text

Ví dụ 1: Dự đoán thẻ cho câu hỏi Stack Overflow

Ví dụ đầu tiên, bạn sẽ tải xuống bộ dữ liệu các câu hỏi lập trình từ Stack Overflow. Mỗi câu hỏi ("Làm cách nào để sắp xếp từ điển theo giá trị?") Được gắn nhãn với chính xác một thẻ ( Python , CSharp , JavaScript hoặc Java ). Nhiệm vụ của bạn là phát triển một mô hình dự đoán thẻ cho một câu hỏi. Đây là một ví dụ về phân loại nhiều lớp, một dạng bài toán học máy quan trọng và có thể áp dụng rộng rãi.

Tải xuống và khám phá tập dữ liệu

Tiếp theo, bạn sẽ tải xuống tập dữ liệu và khám phá cấu trúc thư mục.

data_url = 'https://storage.googleapis.com/download.tensorflow.org/data/stack_overflow_16k.tar.gz'
dataset = utils.get_file(
    'stack_overflow_16k.tar.gz',
    data_url,
    untar=True,
    cache_dir='stack_overflow',
    cache_subdir='')
dataset_dir = pathlib.Path(dataset).parent
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/stack_overflow_16k.tar.gz
6053888/6053168 [==============================] - 0s 0us/step

list(dataset_dir.iterdir())
[PosixPath('/tmp/.keras/README.md'),
 PosixPath('/tmp/.keras/test'),
 PosixPath('/tmp/.keras/stack_overflow_16k.tar.gz.tar.gz'),
 PosixPath('/tmp/.keras/train')]
train_dir = dataset_dir/'train'
list(train_dir.iterdir())
[PosixPath('/tmp/.keras/train/csharp'),
 PosixPath('/tmp/.keras/train/python'),
 PosixPath('/tmp/.keras/train/javascript'),
 PosixPath('/tmp/.keras/train/java')]

Các thư mục train/csharp , train/java , train/pythontrain/javascript chứa nhiều tệp văn bản, mỗi tệp là một câu hỏi về Stack Overflow. In tệp và kiểm tra dữ liệu.

sample_file = train_dir/'python/1755.txt'
with open(sample_file) as f:
  print(f.read())
why does this blank program print true x=true.def stupid():.    x=false.stupid().print x


Tải tập dữ liệu

Tiếp theo, bạn sẽ tải dữ liệu ra đĩa và chuẩn bị nó thành một định dạng phù hợp để đào tạo. Để làm như vậy, bạn sẽ sử dụng tiện ích text_dataset_from_directory để tạo một tf.data.Dataset có nhãn. Nếu bạn chưa quen với tf.data , đây là một bộ sưu tập các công cụ mạnh mẽ để xây dựng đường ống dẫn đầu vào.

preprocessing.text_dataset_from_directory mong đợi một cấu trúc thư mục như sau.

train/
...csharp/
......1.txt
......2.txt
...java/
......1.txt
......2.txt
...javascript/
......1.txt
......2.txt
...python/
......1.txt
......2.txt

Khi chạy thử nghiệm học máy, cách tốt nhất là chia tập dữ liệu của bạn thành ba phần: đào tạo , xác thựckiểm tra . Tập dữ liệu Stack Overflow đã được chia thành huấn luyện và thử nghiệm, nhưng nó thiếu tập hợp xác thực. Tạo bộ xác thực bằng cách sử dụng phần dữ liệu huấn luyện 80:20 bằng cách sử dụng đối số validation_split bên dưới.

batch_size = 32
seed = 42

raw_train_ds = preprocessing.text_dataset_from_directory(
    train_dir,
    batch_size=batch_size,
    validation_split=0.2,
    subset='training',
    seed=seed)
Found 8000 files belonging to 4 classes.
Using 6400 files for training.

Như bạn thấy ở trên, có 8.000 ví dụ trong thư mục đào tạo, trong đó bạn sẽ sử dụng 80% (hoặc 6.400) để đào tạo. Như bạn sẽ thấy trong một khoảnh khắc, bạn có thể đào tạo một mô hình bằng cách thông qua một tf.data.Dataset trực tiếp đến model.fit . Đầu tiên, hãy lặp lại tập dữ liệu và in ra một vài ví dụ để có cảm nhận về dữ liệu.

for text_batch, label_batch in raw_train_ds.take(1):
  for i in range(10):
    print("Question: ", text_batch.numpy()[i][:100], '...')
    print("Label:", label_batch.numpy()[i])
Question:  b'"convert binary to string not works i created a simple program...i create a string and compress it b' ...
Label: 0
Question:  b'"how to calculate sin using system.data.compute() in blank i\'m new here! i\'m a newbie in blank. one ' ...
Label: 0
Question:  b'"how can i execute a js function from the top of the stack? i\'d like to execute a function from the ' ...
Label: 2
Question:  b'"print a reportviewer automatically when you open a form is it possible, when i open a form with rep' ...
Label: 0
Question:  b'"can i use node.childnodes in the if clause? can i do..if (node.childnodes) {.  // do something.}...' ...
Label: 2
Question:  b'"compare strings in array after split in blank i have a string that i use split function on it in or' ...
Label: 1
Question:  b'"adding an array of div ids to a var so i have animate multiple divs across site i found some js on ' ...
Label: 2
Question:  b'"is it necessary for the namespace to be the name of the file in blank? for example, i name my file(' ...
Label: 0
Question:  b'"how can i convert contiguous letters to number separated by dash in blank? i\'d like to convert alph' ...
Label: 1
Question:  b'"ternary operator to minimize code how i can minimize the following code using ternary operator..if ' ...
Label: 0

Các nhãn là 0 , 1 , 2 hoặc 3 . Để xem cái nào trong số này tương ứng với nhãn chuỗi nào, bạn có thể kiểm tra thuộc tính class_names trên tập dữ liệu.

for i, label in enumerate(raw_train_ds.class_names):
  print("Label", i, "corresponds to", label)
Label 0 corresponds to csharp
Label 1 corresponds to java
Label 2 corresponds to javascript
Label 3 corresponds to python

Tiếp theo, bạn sẽ tạo một tập dữ liệu kiểm tra và xác nhận. Bạn sẽ sử dụng 1.600 đánh giá còn lại từ tập huấn luyện để xác nhận.

raw_val_ds = preprocessing.text_dataset_from_directory(
    train_dir,
    batch_size=batch_size,
    validation_split=0.2,
    subset='validation',
    seed=seed)
Found 8000 files belonging to 4 classes.
Using 1600 files for validation.

test_dir = dataset_dir/'test'
raw_test_ds = preprocessing.text_dataset_from_directory(
    test_dir, batch_size=batch_size)
Found 8000 files belonging to 4 classes.

Chuẩn bị tập dữ liệu để đào tạo

Tiếp theo, bạn sẽ chuẩn hóa, mã hóa và vectơ hóa dữ liệu bằng cách sử dụng lớp preprocessing.TextVectorization .

  • Chuẩn hóa đề cập đến việc xử lý trước văn bản, thường là để loại bỏ dấu chấm câu hoặc các phần tử HTML để đơn giản hóa tập dữ liệu.

  • Tokenization đề cập đến việc tách các chuỗi thành các mã thông báo (ví dụ: tách một câu thành các từ riêng lẻ bằng cách tách trên khoảng trắng).

  • Vectorization đề cập đến việc chuyển đổi các mã thông báo thành số để chúng có thể được đưa vào một mạng thần kinh.

Tất cả các nhiệm vụ này có thể được thực hiện với lớp này. Bạn có thể tìm hiểu thêm về từng thứ này trong tài liệu API .

  • Tiêu chuẩn hóa mặc định chuyển đổi văn bản thành chữ thường và loại bỏ dấu chấm câu.

  • Tokenizer mặc định phân chia trên khoảng trắng.

  • Chế độ vector hóa mặc định là int . Điều này xuất ra các chỉ số số nguyên (một trên mỗi mã thông báo). Chế độ này có thể được sử dụng để xây dựng các mô hình có tính đến thứ tự từ. Bạn cũng có thể sử dụng các chế độ khác, như binary , để xây dựng các mô hình từng chữ.

Bạn sẽ xây dựng hai chế độ để tìm hiểu thêm về những điều này. Đầu tiên, bạn sẽ sử dụng mô hình binary để xây dựng một mô hình bag-of-words. Tiếp theo, bạn sẽ sử dụng chế độ int với ConvNet 1D.

VOCAB_SIZE = 10000

binary_vectorize_layer = TextVectorization(
    max_tokens=VOCAB_SIZE,
    output_mode='binary')

Đối với chế độ int , ngoài kích thước từ vựng tối đa, bạn cần đặt độ dài trình tự tối đa rõ ràng, điều này sẽ khiến lớp đệm hoặc cắt ngắn các trình tự thành các giá trị serial_length chính xác.

MAX_SEQUENCE_LENGTH = 250

int_vectorize_layer = TextVectorization(
    max_tokens=VOCAB_SIZE,
    output_mode='int',
    output_sequence_length=MAX_SEQUENCE_LENGTH)

Tiếp theo, bạn sẽ gọi adapt để phù hợp với trạng thái của lớp tiền xử lý với tập dữ liệu. Điều này sẽ khiến mô hình xây dựng một chỉ mục của chuỗi thành số nguyên.

# Make a text-only dataset (without labels), then call adapt
train_text = raw_train_ds.map(lambda text, labels: text)
binary_vectorize_layer.adapt(train_text)
int_vectorize_layer.adapt(train_text)

Xem kết quả của việc sử dụng các lớp này để xử lý trước dữ liệu:

def binary_vectorize_text(text, label):
  text = tf.expand_dims(text, -1)
  return binary_vectorize_layer(text), label
def int_vectorize_text(text, label):
  text = tf.expand_dims(text, -1)
  return int_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_question, first_label = text_batch[0], label_batch[0]
print("Question", first_question)
print("Label", first_label)
Question tf.Tensor(b'"function expected error in blank for dynamically created check box when it is clicked i want to grab the attribute value.it is working in ie 8,9,10 but not working in ie 11,chrome shows function expected error..&lt;input type=checkbox checked=\'checked\' id=\'symptomfailurecodeid\' tabindex=\'54\' style=\'cursor:pointer;\' onclick=chkclickevt(this);  failurecodeid=""1"" &gt;...function chkclickevt(obj) { .    alert(obj.attributes(""failurecodeid""));.}"\n', shape=(), dtype=string)
Label tf.Tensor(2, shape=(), dtype=int32)

print("'binary' vectorized question:", 
      binary_vectorize_text(first_question, first_label)[0])
'binary' vectorized question: tf.Tensor([[1. 1. 1. ... 0. 0. 0.]], shape=(1, 10000), dtype=float32)

print("'int' vectorized question:",
      int_vectorize_text(first_question, first_label)[0])
'int' vectorized question: tf.Tensor(
[[  38  450   65    7   16   12  892  265  186  451   44   11    6  685
     3   46    4 2062    2  485    1    6  158    7  479    1   26   20
   158    7  479    1  502   38  450    1 1767 1763    1    1    1    1
     1    1    1    1    0    0    0    0    0    0    0    0    0    0
     0    0    0    0    0    0    0    0    0    0    0    0    0    0
     0    0    0    0    0    0    0    0    0    0    0    0    0    0
     0    0    0    0    0    0    0    0    0    0    0    0    0    0
     0    0    0    0    0    0    0    0    0    0    0    0    0    0
     0    0    0    0    0    0    0    0    0    0    0    0    0    0
     0    0    0    0    0    0    0    0    0    0    0    0    0    0
     0    0    0    0    0    0    0    0    0    0    0    0    0    0
     0    0    0    0    0    0    0    0    0    0    0    0    0    0
     0    0    0    0    0    0    0    0    0    0    0    0    0    0
     0    0    0    0    0    0    0    0    0    0    0    0    0    0
     0    0    0    0    0    0    0    0    0    0    0    0    0    0
     0    0    0    0    0    0    0    0    0    0    0    0    0    0
     0    0    0    0    0    0    0    0    0    0    0    0    0    0
     0    0    0    0    0    0    0    0    0    0    0    0]], shape=(1, 250), dtype=int64)

Như bạn có thể thấy ở trên, chế độ binary trả về một mảng biểu thị mã thông báo nào tồn tại ít nhất một lần trong đầu vào, trong khi chế độ int thay thế mỗi mã thông báo bằng một số nguyên, do đó bảo toàn thứ tự của chúng. Bạn có thể tra cứu mã thông báo (chuỗi) mà mỗi số nguyên tương ứng bằng cách gọi .get_vocabulary() trên lớp.

print("1289 ---> ", int_vectorize_layer.get_vocabulary()[1289])
print("313 ---> ", int_vectorize_layer.get_vocabulary()[313])
print("Vocabulary size: {}".format(len(int_vectorize_layer.get_vocabulary())))
1289 --->  roman
313 --->  source
Vocabulary size: 10000

Bạn gần như đã sẵn sàng để đào tạo người mẫu của mình. Là bước tiền xử lý cuối cùng, bạn sẽ áp dụng các lớp TextVectorization mà bạn đã tạo trước đó cho tập dữ liệu huấn luyện, xác thực và kiểm tra.

binary_train_ds = raw_train_ds.map(binary_vectorize_text)
binary_val_ds = raw_val_ds.map(binary_vectorize_text)
binary_test_ds = raw_test_ds.map(binary_vectorize_text)

int_train_ds = raw_train_ds.map(int_vectorize_text)
int_val_ds = raw_val_ds.map(int_vectorize_text)
int_test_ds = raw_test_ds.map(int_vectorize_text)

Định cấu hình tập dữ liệu cho hiệu suất

Đây là hai phương pháp quan trọng bạn nên sử dụng khi tải dữ liệu để đảm bảo rằng I / O không bị chặn.

.cache() giữ dữ liệu trong bộ nhớ sau khi nó được tải ra khỏi đĩa. Điều này sẽ đảm bảo tập dữ liệu không trở thành nút cổ chai trong khi đào tạo mô hình của bạn. Nếu tập dữ liệu của bạn quá lớn để vừa với bộ nhớ, bạn cũng có thể sử dụng phương pháp này để tạo bộ đệm ẩn trên đĩa hiệu quả, hiệu quả hơn để đọc so với nhiều tệp nhỏ.

.prefetch() chồng lên quá trình tiền xử lý dữ liệu và thực thi mô hình trong khi đào tạo.

Bạn có thể tìm hiểu thêm về cả hai phương pháp, cũng như cách lưu dữ liệu vào bộ nhớ cache trong hướng dẫn về hiệu suất dữ liệu .

AUTOTUNE = tf.data.experimental.AUTOTUNE

def configure_dataset(dataset):
  return dataset.cache().prefetch(buffer_size=AUTOTUNE)
binary_train_ds = configure_dataset(binary_train_ds)
binary_val_ds = configure_dataset(binary_val_ds)
binary_test_ds = configure_dataset(binary_test_ds)

int_train_ds = configure_dataset(int_train_ds)
int_val_ds = configure_dataset(int_val_ds)
int_test_ds = configure_dataset(int_test_ds)

Đào tạo mô hình

Đã đến lúc tạo mạng nơ-ron của chúng ta. Đối với dữ liệu vectơ binary , hãy đào tạo một mô hình tuyến tính bao gồm các từ đơn giản:

binary_model = tf.keras.Sequential([layers.Dense(4)])
binary_model.compile(
    loss=losses.SparseCategoricalCrossentropy(from_logits=True),
    optimizer='adam',
    metrics=['accuracy'])
history = binary_model.fit(
    binary_train_ds, validation_data=binary_val_ds, epochs=10)
Epoch 1/10
200/200 [==============================] - 2s 12ms/step - loss: 1.1198 - accuracy: 0.6419 - val_loss: 0.9171 - val_accuracy: 0.7669
Epoch 2/10
200/200 [==============================] - 0s 2ms/step - loss: 0.7788 - accuracy: 0.8195 - val_loss: 0.7518 - val_accuracy: 0.7881
Epoch 3/10
200/200 [==============================] - 0s 2ms/step - loss: 0.6274 - accuracy: 0.8634 - val_loss: 0.6655 - val_accuracy: 0.8037
Epoch 4/10
200/200 [==============================] - 1s 3ms/step - loss: 0.5340 - accuracy: 0.8855 - val_loss: 0.6117 - val_accuracy: 0.8169
Epoch 5/10
200/200 [==============================] - 1s 3ms/step - loss: 0.4681 - accuracy: 0.9050 - val_loss: 0.5747 - val_accuracy: 0.8294
Epoch 6/10
200/200 [==============================] - 0s 2ms/step - loss: 0.4178 - accuracy: 0.9189 - val_loss: 0.5479 - val_accuracy: 0.8300
Epoch 7/10
200/200 [==============================] - 1s 3ms/step - loss: 0.3776 - accuracy: 0.9289 - val_loss: 0.5277 - val_accuracy: 0.8338
Epoch 8/10
200/200 [==============================] - 0s 2ms/step - loss: 0.3443 - accuracy: 0.9370 - val_loss: 0.5120 - val_accuracy: 0.8325
Epoch 9/10
200/200 [==============================] - 0s 2ms/step - loss: 0.3161 - accuracy: 0.9427 - val_loss: 0.4997 - val_accuracy: 0.8356
Epoch 10/10
200/200 [==============================] - 0s 2ms/step - loss: 0.2918 - accuracy: 0.9495 - val_loss: 0.4899 - val_accuracy: 0.8394

Tiếp theo, bạn sẽ sử dụng lớp vectơ int để xây dựng Mạng Conv 1D.

def create_model(vocab_size, num_labels):
  model = tf.keras.Sequential([
      layers.Embedding(vocab_size, 64, mask_zero=True),
      layers.Conv1D(64, 5, padding="valid", activation="relu", strides=2),
      layers.GlobalMaxPooling1D(),
      layers.Dense(num_labels)
  ])
  return model
# vocab_size is VOCAB_SIZE + 1 since 0 is used additionally for padding.
int_model = create_model(vocab_size=VOCAB_SIZE + 1, num_labels=4)
int_model.compile(
    loss=losses.SparseCategoricalCrossentropy(from_logits=True),
    optimizer='adam',
    metrics=['accuracy'])
history = int_model.fit(int_train_ds, validation_data=int_val_ds, epochs=5)
Epoch 1/5
200/200 [==============================] - 4s 18ms/step - loss: 1.1293 - accuracy: 0.5183 - val_loss: 0.7424 - val_accuracy: 0.7100
Epoch 2/5
200/200 [==============================] - 2s 9ms/step - loss: 0.6095 - accuracy: 0.7727 - val_loss: 0.5349 - val_accuracy: 0.8062
Epoch 3/5
200/200 [==============================] - 2s 9ms/step - loss: 0.3565 - accuracy: 0.8892 - val_loss: 0.4734 - val_accuracy: 0.8125
Epoch 4/5
200/200 [==============================] - 2s 9ms/step - loss: 0.1898 - accuracy: 0.9559 - val_loss: 0.4760 - val_accuracy: 0.8194
Epoch 5/5
200/200 [==============================] - 2s 9ms/step - loss: 0.0909 - accuracy: 0.9864 - val_loss: 0.5039 - val_accuracy: 0.8144

So sánh hai mô hình:

print("Linear model on binary vectorized data:")
print(binary_model.summary())
Linear model on binary vectorized data:
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 4)                 40004     
=================================================================
Total params: 40,004
Trainable params: 40,004
Non-trainable params: 0
_________________________________________________________________
None

print("ConvNet model on int vectorized data:")
print(int_model.summary())
ConvNet model on int vectorized data:
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding (Embedding)        (None, None, 64)          640064    
_________________________________________________________________
conv1d (Conv1D)              (None, None, 64)          20544     
_________________________________________________________________
global_max_pooling1d (Global (None, 64)                0         
_________________________________________________________________
dense_1 (Dense)              (None, 4)                 260       
=================================================================
Total params: 660,868
Trainable params: 660,868
Non-trainable params: 0
_________________________________________________________________
None

Đánh giá cả hai mô hình trên dữ liệu thử nghiệm:

binary_loss, binary_accuracy = binary_model.evaluate(binary_test_ds)
int_loss, int_accuracy = int_model.evaluate(int_test_ds)

print("Binary model accuracy: {:2.2%}".format(binary_accuracy))
print("Int model accuracy: {:2.2%}".format(int_accuracy))
250/250 [==============================] - 2s 8ms/step - loss: 0.5178 - accuracy: 0.8141
250/250 [==============================] - 2s 10ms/step - loss: 0.5194 - accuracy: 0.8091
Binary model accuracy: 81.41%
Int model accuracy: 80.91%

Xuất mô hình

Trong đoạn mã trên, bạn đã áp dụng lớp TextVectorization cho tập dữ liệu trước khi cung cấp văn bản cho mô hình. Nếu bạn muốn làm cho mô hình của mình có khả năng xử lý chuỗi thô (ví dụ: để đơn giản hóa việc triển khai nó), bạn có thể bao gồm lớp TextVectorization bên trong mô hình của mình. Để làm như vậy, bạn có thể tạo một mô hình mới bằng cách sử dụng trọng lượng bạn vừa tập.

export_model = tf.keras.Sequential(
    [binary_vectorize_layer, binary_model,
     layers.Activation('sigmoid')])

export_model.compile(
    loss=losses.SparseCategoricalCrossentropy(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: {:2.2%}".format(binary_accuracy))
250/250 [==============================] - 3s 11ms/step - loss: 0.7002 - accuracy: 0.8141
Accuracy: 81.41%

Giờ đây, mô hình của bạn có thể lấy các chuỗi thô làm đầu vào và dự đoán điểm cho từng nhãn bằng cách sử dụng model.predict . Xác định một hàm để tìm nhãn có điểm tối đa:

def get_string_labels(predicted_scores_batch):
  predicted_int_labels = tf.argmax(predicted_scores_batch, axis=1)
  predicted_labels = tf.gather(raw_train_ds.class_names, predicted_int_labels)
  return predicted_labels

Chạy suy luận trên dữ liệu mới

inputs = [
    "how do I extract keys from a dict into a list?",  # python
    "debug public static void main(string[] args) {...}",  # java
]
predicted_scores = export_model.predict(inputs)
predicted_labels = get_string_labels(predicted_scores)
for input, label in zip(inputs, predicted_labels):
  print("Question: ", input)
  print("Predicted label: ", label.numpy())
Question:  how do I extract keys from a dict into a list?
Predicted label:  b'python'
Question:  debug public static void main(string[] args) {...}
Predicted label:  b'java'

Việc bao gồm logic tiền xử lý văn bản bên trong mô hình của bạn cho phép bạn xuất một mô hình để sản xuất giúp đơn giản hóa việc triển khai và giảm khả năng sai lệch đào tạo / thử nghiệm .

Có một sự khác biệt về hiệu suất cần lưu ý khi chọn vị trí áp dụng lớp TextVectorization của bạn. Sử dụng nó bên ngoài mô hình của bạn cho phép bạn xử lý CPU không đồng bộ và lưu vào bộ đệm dữ liệu của bạn khi đào tạo về GPU. Vì vậy, nếu bạn đang đào tạo mô hình của mình trên GPU, bạn có thể muốn sử dụng tùy chọn này để có được hiệu suất tốt nhất trong khi phát triển mô hình của mình, sau đó chuyển sang bao gồm lớp TextVectorization bên trong mô hình của bạn khi bạn sẵn sàng chuẩn bị triển khai .

Truy cập hướng dẫn này để tìm hiểu thêm về các mô hình tiết kiệm.

Ví dụ 2: Dự đoán tác giả của các bản dịch Illiad

Phần sau cung cấp một ví dụ về việc sử dụng tf.data.TextLineDataset để tải các ví dụ từ tệp văn bản và tf.text để xử lý trước dữ liệu. Trong ví dụ này, bạn sẽ sử dụng ba bản dịch tiếng Anh khác nhau của cùng một tác phẩm, Illiad của Homer, và đào tạo một mô hình để xác định người dịch cho một dòng văn bản.

Tải xuống và khám phá tập dữ liệu

Các văn bản của ba bản dịch là:

Các tệp văn bản được sử dụng trong hướng dẫn này đã trải qua một số tác vụ tiền xử lý điển hình như xóa đầu trang và chân trang của tài liệu, số dòng và tiêu đề chương. Tải xuống cục bộ các tệp tin nhẹ này.

DIRECTORY_URL = 'https://storage.googleapis.com/download.tensorflow.org/data/illiad/'
FILE_NAMES = ['cowper.txt', 'derby.txt', 'butler.txt']

for name in FILE_NAMES:
  text_dir = utils.get_file(name, origin=DIRECTORY_URL + name)

parent_dir = pathlib.Path(text_dir).parent
list(parent_dir.iterdir())
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/illiad/cowper.txt
819200/815980 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/illiad/derby.txt
811008/809730 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/illiad/butler.txt
811008/807992 [==============================] - 0s 0us/step

[PosixPath('/root/.keras/datasets/derby.txt'),
 PosixPath('/root/.keras/datasets/cowper.txt'),
 PosixPath('/root/.keras/datasets/butler.txt')]

Tải tập dữ liệu

Bạn sẽ sử dụng TextLineDataset , được thiết kế để tạo tf.data.Dataset từ tệp văn bản, trong đó mỗi ví dụ là một dòng văn bản từ tệp gốc, trong khi text_dataset_from_directory xử lý tất cả nội dung của tệp như một ví dụ duy nhất. TextLineDataset hữu ích cho dữ liệu văn bản chủ yếu dựa trên dòng (ví dụ: thơ hoặc nhật ký lỗi).

Lặp đi lặp lại các tệp này, tải từng tệp vào tập dữ liệu của riêng nó. Mỗi ví dụ cần được gắn nhãn riêng, vì vậy hãy sử dụng tf.data.Dataset.map để áp dụng một chức năng của trình gắn nhãn cho từng ví dụ. Điều này sẽ lặp lại mọi ví dụ trong tập dữ liệu, trả về các cặp ( example, label ).

def labeler(example, index):
  return example, tf.cast(index, tf.int64)
labeled_data_sets = []

for i, file_name in enumerate(FILE_NAMES):
  lines_dataset = tf.data.TextLineDataset(str(parent_dir/file_name))
  labeled_dataset = lines_dataset.map(lambda ex: labeler(ex, i))
  labeled_data_sets.append(labeled_dataset)

Tiếp theo, bạn sẽ kết hợp các tập dữ liệu được gắn nhãn này thành một tập dữ liệu duy nhất và xáo trộn nó.

BUFFER_SIZE = 50000
BATCH_SIZE = 64
VALIDATION_SIZE = 5000
all_labeled_data = labeled_data_sets[0]
for labeled_dataset in labeled_data_sets[1:]:
  all_labeled_data = all_labeled_data.concatenate(labeled_dataset)

all_labeled_data = all_labeled_data.shuffle(
    BUFFER_SIZE, reshuffle_each_iteration=False)

In ra một vài ví dụ như trước đây. Tập dữ liệu chưa được phân lô, do đó mỗi mục nhập trong all_labeled_data tương ứng với một điểm dữ liệu:

for text, label in all_labeled_data.take(10):
  print("Sentence: ", text.numpy())
  print("Label:", label.numpy())
Sentence:  b"By the brisk breeze impell'd, and winnower's force;"
Label: 1
Sentence:  b"On this a brazen canister she plac'd,"
Label: 1
Sentence:  b'Trod in his steps, ere settled yet the dust.'
Label: 1
Sentence:  b'And stately \xc3\x86py. Their confederate powers'
Label: 0
Sentence:  b'Ill-fated parents both! nor thou to him,'
Label: 1
Sentence:  b'Let him not seek to terrify with force'
Label: 0
Sentence:  b'the tomb of Aepytus, where the people fight hand to hand; the men of'
Label: 2
Sentence:  b"And Theseus, AEgeus' more than mortal son."
Label: 1
Sentence:  b'To whom in wrath Achilles swift of foot;'
Label: 1
Sentence:  b'The lance of Diomed, behind his neck,'
Label: 1

Chuẩn bị tập dữ liệu để đào tạo

Thay vì sử dụng lớp TextVectorization để xử lý trước tập dữ liệu văn bản của chúng tôi, giờ đây bạn sẽ sử dụng API tf.text để chuẩn hóa và mã hóa dữ liệu, xây dựng từ vựng và sử dụng StaticVocabularyTable để ánh xạ mã thông báo thành số nguyên để cấp cho mô hình.

Trong khi tf.text cung cấp nhiều trình mã hóa khác nhau, bạn sẽ sử dụng trình UnicodeScriptTokenizer để mã hóa tập dữ liệu của chúng tôi. Xác định một chức năng để chuyển đổi văn bản thành chữ thường và mã hóa nó. Bạn sẽ sử dụng tf.data.Dataset.map để áp dụng mã hóa cho tập dữ liệu.

tokenizer = tf_text.UnicodeScriptTokenizer()
def tokenize(text, unused_label):
  lower_case = tf_text.case_fold_utf8(text)
  return tokenizer.tokenize(lower_case)
tokenized_ds = all_labeled_data.map(tokenize)
WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/util/dispatch.py:201: batch_gather (from tensorflow.python.ops.array_ops) is deprecated and will be removed after 2017-10-25.
Instructions for updating:
`tf.batch_gather` is deprecated, please use `tf.gather` with `batch_dims=-1` instead.

Bạn có thể lặp lại tập dữ liệu và in ra một vài ví dụ được mã hóa.

for text_batch in tokenized_ds.take(5):
  print("Tokens: ", text_batch.numpy())
Tokens:  [b'by' b'the' b'brisk' b'breeze' b'impell' b"'" b'd' b',' b'and'
 b'winnower' b"'" b's' b'force' b';']
Tokens:  [b'on' b'this' b'a' b'brazen' b'canister' b'she' b'plac' b"'" b'd' b',']
Tokens:  [b'trod' b'in' b'his' b'steps' b',' b'ere' b'settled' b'yet' b'the'
 b'dust' b'.']
Tokens:  [b'and' b'stately' b'\xc3\xa6py' b'.' b'their' b'confederate' b'powers']
Tokens:  [b'ill' b'-' b'fated' b'parents' b'both' b'!' b'nor' b'thou' b'to' b'him'
 b',']

Tiếp theo, bạn sẽ xây dựng vốn từ vựng bằng cách sắp xếp các mã thông báo theo tần suất và giữ các mã thông báo VOCAB_SIZE hàng đầu.

tokenized_ds = configure_dataset(tokenized_ds)

vocab_dict = collections.defaultdict(lambda: 0)
for toks in tokenized_ds.as_numpy_iterator():
  for tok in toks:
    vocab_dict[tok] += 1

vocab = sorted(vocab_dict.items(), key=lambda x: x[1], reverse=True)
vocab = [token for token, count in vocab]
vocab = vocab[:VOCAB_SIZE]
vocab_size = len(vocab)
print("Vocab size: ", vocab_size)
print("First five vocab entries:", vocab[:5])
Vocab size:  10000
First five vocab entries: [b',', b'the', b'and', b"'", b'of']

Để chuyển đổi mã thông báo thành số nguyên, hãy sử dụng bộ vocab để tạo StaticVocabularyTable . Bạn sẽ ánh xạ mã thông báo thành các số nguyên trong phạm vi [ 2 , vocab_size + 2 ]. Như với lớp TextVectorization , 0 được dành riêng để biểu thị phần đệm và 1 được dành riêng để biểu thị mã thông báo ngoài từ vựng (OOV).

keys = vocab
values = range(2, len(vocab) + 2)  # reserve 0 for padding, 1 for OOV

init = tf.lookup.KeyValueTensorInitializer(
    keys, values, key_dtype=tf.string, value_dtype=tf.int64)

num_oov_buckets = 1
vocab_table = tf.lookup.StaticVocabularyTable(init, num_oov_buckets)

Cuối cùng, xác định một fuction để chuẩn hóa, mã hóa và vectơ hóa tập dữ liệu bằng cách sử dụng bảng tra cứu và mã hóa:

def preprocess_text(text, label):
  standardized = tf_text.case_fold_utf8(text)
  tokenized = tokenizer.tokenize(standardized)
  vectorized = vocab_table.lookup(tokenized)
  return vectorized, label

Bạn có thể thử điều này trên một ví dụ duy nhất để xem kết quả:

example_text, example_label = next(iter(all_labeled_data))
print("Sentence: ", example_text.numpy())
vectorized_text, example_label = preprocess_text(example_text, example_label)
print("Vectorized sentence: ", vectorized_text.numpy())
Sentence:  b"By the brisk breeze impell'd, and winnower's force;"
Vectorized sentence:  [  26    3 3286 2263 1959    5    9    2    4 7806    5   29  260   10]

Bây giờ, hãy chạy chức năng tiền xử lý trên tập dữ liệu bằng tf.data.Dataset.map .

all_encoded_data = all_labeled_data.map(preprocess_text)

Chia tập dữ liệu thành huấn luyện và kiểm tra

Lớp Keras TextVectorization cũng phân lô và đệm dữ liệu được vector hóa. Phần đệm là bắt buộc vì các ví dụ bên trong một lô cần có cùng kích thước và hình dạng, nhưng các ví dụ trong các tập dữ liệu này không phải tất cả cùng kích thước - mỗi dòng văn bản có một số từ khác nhau. tf.data.Dataset hỗ trợ các tập dữ liệu chia nhỏ và đệm theo lô:

train_data = all_encoded_data.skip(VALIDATION_SIZE).shuffle(BUFFER_SIZE)
validation_data = all_encoded_data.take(VALIDATION_SIZE)
train_data = train_data.padded_batch(BATCH_SIZE)
validation_data = validation_data.padded_batch(BATCH_SIZE)

Bây giờ, validation_datatrain_data không phải là tập hợp của các cặp ( example, label ) mà là tập hợp của các lô. Mỗi lô là một cặp ( nhiều ví dụ , nhiều nhãn ) được biểu diễn dưới dạng mảng. Để minh họa:

sample_text, sample_labels = next(iter(validation_data))
print("Text batch shape: ", sample_text.shape)
print("Label batch shape: ", sample_labels.shape)
print("First text example: ", sample_text[0])
print("First label example: ", sample_labels[0])
Text batch shape:  (64, 18)
Label batch shape:  (64,)
First text example:  tf.Tensor(
[  26    3 3286 2263 1959    5    9    2    4 7806    5   29  260   10
    0    0    0    0], shape=(18,), dtype=int64)
First label example:  tf.Tensor(1, shape=(), dtype=int64)

Vì chúng tôi sử dụng 0 cho phần đệm và 1 cho mã thông báo từ vựng (OOV), kích thước từ vựng đã tăng lên hai.

vocab_size += 2

Định cấu hình bộ dữ liệu để có hiệu suất tốt hơn như trước đây.

train_data = configure_dataset(train_data)
validation_data = configure_dataset(validation_data)

Đào tạo mô hình

Bạn có thể đào tạo một mô hình trên tập dữ liệu này như trước đây.

model = create_model(vocab_size=vocab_size, num_labels=3)
model.compile(
    optimizer='adam',
    loss=losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=['accuracy'])
history = model.fit(train_data, validation_data=validation_data, epochs=3)
Epoch 1/3
697/697 [==============================] - 9s 13ms/step - loss: 0.5224 - accuracy: 0.7665 - val_loss: 0.3657 - val_accuracy: 0.8460
Epoch 2/3
697/697 [==============================] - 6s 8ms/step - loss: 0.2834 - accuracy: 0.8836 - val_loss: 0.3596 - val_accuracy: 0.8488
Epoch 3/3
697/697 [==============================] - 6s 9ms/step - loss: 0.1914 - accuracy: 0.9262 - val_loss: 0.3951 - val_accuracy: 0.8476

loss, accuracy = model.evaluate(validation_data)

print("Loss: ", loss)
print("Accuracy: {:2.2%}".format(accuracy))
79/79 [==============================] - 0s 2ms/step - loss: 0.3951 - accuracy: 0.8476
Loss:  0.39514628052711487
Accuracy: 84.76%

Xuất mô hình

Để làm cho mô hình của chúng tôi có khả năng lấy các chuỗi thô làm đầu vào, bạn sẽ tạo một lớp TextVectorization thực hiện các bước tương tự như chức năng tiền xử lý tùy chỉnh của chúng tôi. Vì bạn đã luyện từ vựng, bạn có thể sử dụng set_vocaublary thay vì adapt để luyện từ vựng mới.

preprocess_layer = TextVectorization(
    max_tokens=vocab_size,
    standardize=tf_text.case_fold_utf8,
    split=tokenizer.tokenize,
    output_mode='int',
    output_sequence_length=MAX_SEQUENCE_LENGTH)
preprocess_layer.set_vocabulary(vocab)
export_model = tf.keras.Sequential(
    [preprocess_layer, model,
     layers.Activation('sigmoid')])

export_model.compile(
    loss=losses.SparseCategoricalCrossentropy(from_logits=False),
    optimizer='adam',
    metrics=['accuracy'])
# Create a test dataset of raw strings
test_ds = all_labeled_data.take(VALIDATION_SIZE).batch(BATCH_SIZE)
test_ds = configure_dataset(test_ds)
loss, accuracy = export_model.evaluate(test_ds)
print("Loss: ", loss)
print("Accuracy: {:2.2%}".format(accuracy))
79/79 [==============================] - 1s 10ms/step - loss: 0.5304 - accuracy: 0.7978
Loss:  0.5304141640663147
Accuracy: 79.78%

Sự mất mát và độ chính xác đối với mô hình trên tập hợp xác thực được mã hóa và mô hình đã xuất trên tập hợp xác thực thô là như nhau, như mong đợi.

Chạy suy luận trên dữ liệu mới

inputs = [
    "Join'd to th' Ionians with their flowing robes,",  # Label: 1
    "the allies, and his armour flashed about him so that he seemed to all",  # Label: 2
    "And with loud clangor of his arms he fell.",  # Label: 0
]
predicted_scores = export_model.predict(inputs)
predicted_labels = tf.argmax(predicted_scores, axis=1)
for input, label in zip(inputs, predicted_labels):
  print("Question: ", input)
  print("Predicted label: ", label.numpy())
Question:  Join'd to th' Ionians with their flowing robes,
Predicted label:  1
Question:  the allies, and his armour flashed about him so that he seemed to all
Predicted label:  2
Question:  And with loud clangor of his arms he fell.
Predicted label:  0

Tải xuống các bộ dữ liệu khác bằng Bộ dữ liệu TensorFlow (TFDS)

Bạn có thể tải xuống nhiều bộ dữ liệu khác từ Bộ dữ liệu TensorFlow . Ví dụ: bạn sẽ tải xuống bộ dữ liệu IMDB Large Movie Review và sử dụng nó để đào tạo một mô hình phân loại tình cảm.

train_ds = tfds.load(
    'imdb_reviews',
    split='train',
    batch_size=BATCH_SIZE,
    shuffle_files=True,
    as_supervised=True)
Downloading and preparing dataset imdb_reviews/plain_text/1.0.0 (download: 80.23 MiB, generated: Unknown size, total: 80.23 MiB) to /root/tensorflow_datasets/imdb_reviews/plain_text/1.0.0...

HBox(children=(FloatProgress(value=1.0, bar_style='info', description='Dl Completed...', max=1.0, style=Progre…
HBox(children=(FloatProgress(value=1.0, bar_style='info', description='Dl Size...', max=1.0, style=ProgressSty…





HBox(children=(FloatProgress(value=1.0, bar_style='info', max=1.0), HTML(value='')))
Shuffling and writing examples to /root/tensorflow_datasets/imdb_reviews/plain_text/1.0.0.incompleteBKTU7R/imdb_reviews-train.tfrecord

HBox(children=(FloatProgress(value=0.0, max=25000.0), HTML(value='')))

HBox(children=(FloatProgress(value=1.0, bar_style='info', max=1.0), HTML(value='')))
Shuffling and writing examples to /root/tensorflow_datasets/imdb_reviews/plain_text/1.0.0.incompleteBKTU7R/imdb_reviews-test.tfrecord

HBox(children=(FloatProgress(value=0.0, max=25000.0), HTML(value='')))

HBox(children=(FloatProgress(value=1.0, bar_style='info', max=1.0), HTML(value='')))
Shuffling and writing examples to /root/tensorflow_datasets/imdb_reviews/plain_text/1.0.0.incompleteBKTU7R/imdb_reviews-unsupervised.tfrecord

HBox(children=(FloatProgress(value=0.0, max=50000.0), HTML(value='')))
Dataset imdb_reviews downloaded and prepared to /root/tensorflow_datasets/imdb_reviews/plain_text/1.0.0. Subsequent calls will reuse this data.

val_ds = tfds.load(
    'imdb_reviews',
    split='train',
    batch_size=BATCH_SIZE,
    shuffle_files=True,
    as_supervised=True)

In một vài ví dụ.

for review_batch, label_batch in val_ds.take(1):
  for i in range(5):
    print("Review: ", review_batch[i].numpy())
    print("Label: ", label_batch[i].numpy())
Review:  b"This was an absolutely terrible movie. Don't be lured in by Christopher Walken or Michael Ironside. Both are great actors, but this must simply be their worst role in history. Even their great acting could not redeem this movie's ridiculous storyline. This movie is an early nineties US propaganda piece. The most pathetic scenes were those when the Columbian rebels were making their cases for revolutions. Maria Conchita Alonso appeared phony, and her pseudo-love affair with Walken was nothing but a pathetic emotional plug in a movie that was devoid of any real meaning. I am disappointed that there are movies like this, ruining actor's like Christopher Walken's good name. I could barely sit through it."
Label:  0
Review:  b'I have been known to fall asleep during films, but this is usually due to a combination of things including, really tired, being warm and comfortable on the sette and having just eaten a lot. However on this occasion I fell asleep because the film was rubbish. The plot development was constant. Constantly slow and boring. Things seemed to happen, but with no explanation of what was causing them or why. I admit, I may have missed part of the film, but i watched the majority of it and everything just seemed to happen of its own accord without any real concern for anything else. I cant recommend this film at all.'
Label:  0
Review:  b'Mann photographs the Alberta Rocky Mountains in a superb fashion, and Jimmy Stewart and Walter Brennan give enjoyable performances as they always seem to do. <br /><br />But come on Hollywood - a Mountie telling the people of Dawson City, Yukon to elect themselves a marshal (yes a marshal!) and to enforce the law themselves, then gunfighters battling it out on the streets for control of the town? <br /><br />Nothing even remotely resembling that happened on the Canadian side of the border during the Klondike gold rush. Mr. Mann and company appear to have mistaken Dawson City for Deadwood, the Canadian North for the American Wild West.<br /><br />Canadian viewers be prepared for a Reefer Madness type of enjoyable howl with this ludicrous plot, or, to shake your head in disgust.'
Label:  0
Review:  b'This is the kind of film for a snowy Sunday afternoon when the rest of the world can go ahead with its own business as you descend into a big arm-chair and mellow for a couple of hours. Wonderful performances from Cher and Nicolas Cage (as always) gently row the plot along. There are no rapids to cross, no dangerous waters, just a warm and witty paddle through New York life at its best. A family film in every sense and one that deserves the praise it received.'
Label:  1
Review:  b'As others have mentioned, all the women that go nude in this film are mostly absolutely gorgeous. The plot very ably shows the hypocrisy of the female libido. When men are around they want to be pursued, but when no "men" are around, they become the pursuers of a 14 year old boy. And the boy becomes a man really fast (we should all be so lucky at this age!). He then gets up the courage to pursue his true love.'
Label:  1

Bây giờ bạn có thể xử lý trước dữ liệu và đào tạo một mô hình như trước đây.

Chuẩn bị tập dữ liệu để đào tạo

vectorize_layer = TextVectorization(
    max_tokens=VOCAB_SIZE,
    output_mode='int',
    output_sequence_length=MAX_SEQUENCE_LENGTH)

# Make a text-only dataset (without labels), then call adapt
train_text = train_ds.map(lambda text, labels: text)
vectorize_layer.adapt(train_text)
def vectorize_text(text, label):
  text = tf.expand_dims(text, -1)
  return vectorize_layer(text), label
train_ds = train_ds.map(vectorize_text)
val_ds = val_ds.map(vectorize_text)
# Configure datasets for performance as before
train_ds = configure_dataset(train_ds)
val_ds = configure_dataset(val_ds)

Đào tạo mô hình

model = create_model(vocab_size=VOCAB_SIZE + 1, num_labels=1)
model.summary()
Model: "sequential_5"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_2 (Embedding)      (None, None, 64)          640064    
_________________________________________________________________
conv1d_2 (Conv1D)            (None, None, 64)          20544     
_________________________________________________________________
global_max_pooling1d_2 (Glob (None, 64)                0         
_________________________________________________________________
dense_3 (Dense)              (None, 1)                 65        
=================================================================
Total params: 660,673
Trainable params: 660,673
Non-trainable params: 0
_________________________________________________________________

model.compile(
    loss=losses.BinaryCrossentropy(from_logits=True),
    optimizer='adam',
    metrics=['accuracy'])
history = model.fit(train_ds, validation_data=val_ds, epochs=3)
Epoch 1/3
391/391 [==============================] - 9s 23ms/step - loss: 0.4976 - accuracy: 0.7044 - val_loss: 0.2976 - val_accuracy: 0.8832
Epoch 2/3
391/391 [==============================] - 5s 14ms/step - loss: 0.2748 - accuracy: 0.8801 - val_loss: 0.1696 - val_accuracy: 0.9458
Epoch 3/3
391/391 [==============================] - 6s 14ms/step - loss: 0.1697 - accuracy: 0.9351 - val_loss: 0.0956 - val_accuracy: 0.9770

loss, accuracy = model.evaluate(val_ds)

print("Loss: ", loss)
print("Accuracy: {:2.2%}".format(accuracy))
391/391 [==============================] - 1s 3ms/step - loss: 0.0956 - accuracy: 0.9770
Loss:  0.09558165073394775
Accuracy: 97.70%

Xuất mô hình

export_model = tf.keras.Sequential(
    [vectorize_layer, model,
     layers.Activation('sigmoid')])

export_model.compile(
    loss=losses.SparseCategoricalCrossentropy(from_logits=False),
    optimizer='adam',
    metrics=['accuracy'])
# 0 --> negative review
# 1 --> positive review
inputs = [
    "This is a fantastic movie.",
    "This is a bad movie.",
    "This movie was so bad that it was good.",
    "I will never say yes to watching this movie.",
]
predicted_scores = export_model.predict(inputs)
predicted_labels = [int(round(x[0])) for x in predicted_scores]
for input, label in zip(inputs, predicted_labels):
  print("Question: ", input)
  print("Predicted label: ", label)
Question:  This is a fantastic movie.
Predicted label:  1
Question:  This is a bad movie.
Predicted label:  0
Question:  This movie was so bad that it was good.
Predicted label:  0
Question:  I will never say yes to watching this movie.
Predicted label:  1

Phần kết luận

Hướng dẫn này trình bày một số cách để tải và xử lý trước văn bản. Bước tiếp theo, bạn có thể khám phá các hướng dẫn bổ sung trên trang web hoặc tải xuống bộ dữ liệu mới từ Bộ dữ liệu TensorFlow .