Tensorflow2.0学习-加载和预处理数据 (七)
文章目錄
- 圖像
- 引包
- 數據準備
- 下載數據
- 隨機打印數據
- 查看圖片
- 圖對應的標簽
- 加載格式化圖片
- tf.data.Dataset
- 跑起來
- 數據集訓練參數設置
- 傳入模型中
- 總結
- CSV
- 引包
- 數據準備
- 數據預處理
- 離散的數據
- 連續的浮點數據
- 模型準備
- 跑起來
- Numpy
- 引包
- 數據準備
- 跑起來
- pandas dataframes
- 引包
- 數據準備
- 讀取數據
- 模型準備并跑起來
- 代替特征列
- TFRecord 和 tf.Example
- 文本數據
- 引包
- 數據準備
- 數據變成 tf.data.TextLineDataset
- 數據變為數字變量
- 劃分訓練測試集
- 模型準備
- 跑起來
- 總結
圖像
官方圖像
引包
import tensorflow as tf AUTOTUNE = tf.data.experimental.AUTOTUNE數據準備
下載數據
import pathlib data_root_orig = tf.keras.utils.get_file(origin='https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz',fname='flower_photos', untar=True) data_root = pathlib.Path(data_root_orig) print(data_root)隨機打印數據
for item in data_root.iterdir():print(item)import random all_image_paths = list(data_root.glob('*/*')) all_image_paths = [str(path) for path in all_image_paths] random.shuffle(all_image_paths)image_count = len(all_image_paths) print(image_count)查看圖片
原來的網頁是用了IPython包,但是得用jupyter才能顯示,這里我改成matplotlib
import matplotlib.pyplot as plt # plt 用于顯示圖片 from PIL import Imagedef display(path):img = Image.open(path)plt.imshow(img)plt.show()def caption_image(image_path):image_rel = pathlib.Path(image_path).relative_to(data_root)return "Image (CC BY 2.0) " + ' - '.join(attributions[str(image_rel).replace('\\', '/')].split(' - ')[:-1])for n in range(3):image_path = random.choice(all_image_paths)display(image_path)print(caption_image(image_path))print()有一說一,這些個花的照片還蠻好看的。
圖對應的標簽
將圖對應的標簽打印出來,再給他們附上數字編號。
label_names = sorted(item.name for item in data_root.glob('*/') if item.is_dir()) print(label_names)label_to_index = dict((name, index) for index, name in enumerate(label_names)) print(label_to_index)再將每個圖片的標簽值對應上
all_image_labels = [label_to_index[pathlib.Path(path).parent.name]for path in all_image_paths]print("First 10 labels indices: ", all_image_labels[:10])現在標簽數組all_image_labels和圖片路徑數組all_image_paths都有了。
加載格式化圖片
這個就可以將圖片格式化,標準大小以及歸一化。
def preprocess_image(image):image = tf.image.decode_jpeg(image, channels=3)image = tf.image.resize(image, [192, 192])image /= 255.0 # normalize to [0,1] rangereturn imagedef load_and_preprocess_image(path):image = tf.io.read_file(path)return preprocess_image(image)import matplotlib.pyplot as pltimage_path = all_image_paths[0] label = all_image_labels[0]plt.imshow(load_and_preprocess_image(img_path)) plt.grid(False) plt.xlabel(caption_image(img_path)) plt.title(label_names[label].title()) print()tf.data.Dataset
來看看官方的加載工具吧。
首先將所有圖片的路徑押進TensorSliceDataset里。再用map動態加載格式化圖片。
既然圖片可以,那么標簽也可以
label_ds = tf.data.Dataset.from_tensor_slices(tf.cast(all_image_labels, tf.int64)) for label in label_ds.take(10):print(label_names[label.numpy()])然后用zip打包起來,這樣image_label_ds,出來就有圖和標簽了。
image_label_ds = tf.data.Dataset.zip((image_ds, label_ds))注意:當你擁有形似 all_image_labels 和 all_image_paths的數組,tf.data.dataset.Dataset.zip 的替代方法是將這對數組切片。
ds = tf.data.Dataset.from_tensor_slices((all_image_paths, all_image_labels))# 元組被解壓縮到映射函數的位置參數中 def load_and_preprocess_from_path_label(path, label):return load_and_preprocess_image(path), labelimage_label_ds = ds.map(load_and_preprocess_from_path_label) image_label_ds跑起來
數據集訓練參數設置
BATCH_SIZE = 32# 設置一個和數據集大小一致的 shuffle buffer size(隨機緩沖區大小)以保證數據 # 被充分打亂。 ds = image_label_ds.shuffle(buffer_size=image_count) # 將數據進行順序打亂 ds = ds.repeat() # 可以重復選取 ds = ds.batch(BATCH_SIZE) # 被切割為batch # 當模型在訓練的時候,`prefetch` 使數據集在后臺取得 batch。 ds = ds.prefetch(buffer_size=AUTOTUNE)在隨機緩沖區完全為空之前,被打亂的數據集不會報告數據集的結尾。Dataset(數據集)由 .repeat重新啟動,導致需要再次等待隨機緩沖區被填滿。
可以通過使用 tf.data.Dataset.apply 方法和融合過的tf.data.experimental.shuffle_and_repeat 函數來解決
ds = image_label_ds.apply(tf.data.experimental.shuffle_and_repeat(buffer_size=image_count)) ds = ds.batch(BATCH_SIZE) ds = ds.prefetch(buffer_size=AUTOTUNE) ds傳入模型中
直接就是存在tf.keras.applications里的一個副本,這個MobileNetV2是不可訓練的
mobile_net = tf.keras.applications.MobileNetV2(input_shape=(192, 192, 3), include_top=False) mobile_net.trainable=False看下網絡傳入數據的要求
help(tf.keras.applications.mobilenet_v2.preprocess_input)要變成(-1,1)
def change_range(image,label):return 2*image-1, labelkeras_ds = ds.map(change_range)來一個批次先看看
# 數據集可能需要幾秒來啟動,因為要填滿其隨機緩沖區。 image_batch, label_batch = next(iter(keras_ds)) feature_map_batch = mobile_net(image_batch) print(feature_map_batch.shape)結果
(32, 6, 6, 1280)再處理,做自己的模型,再輸出看看
model = tf.keras.Sequential([mobile_net,tf.keras.layers.GlobalAveragePooling2D(),tf.keras.layers.Dense(len(label_names), activation = 'softmax')])logit_batch = model(image_batch).numpy()print("min logit:", logit_batch.min()) print("max logit:", logit_batch.max()) print()print("Shape:", logit_batch.shape)結果
min logit: 0.004120019 max logit: 0.6654783 Shape: (32, 5)對模型進行一些設置,稍微跑一下
model.compile(optimizer=tf.keras.optimizers.Adam(),loss='sparse_categorical_crossentropy',metrics=["accuracy"]) model.fit(ds, epochs=1, steps_per_epoch=3)結果
3/3 [==============================] - 0s 165ms/step - loss: 2.0662 - accuracy: 0.1667 Out[37]: <tensorflow.python.keras.callbacks.History at 0x16f3f3d2ac0>可以加入緩存,提高訓練效率,GPU不同等待CPU填完數據再運行。
ds = image_label_ds.cache() ds = ds.apply(tf.data.experimental.shuffle_and_repeat(buffer_size=image_count)) ds = ds.batch(BATCH_SIZE).prefetch(buffer_size=AUTOTUNE)總結
首先有圖片和標簽,圖片用圖片存放地址代替。可以保證一個地址一個標簽,用的時候,直接映射讀出圖片。
# 圖片路徑和標簽分別tf.data.Dataset path_ds = tf.data.Dataset.from_tensor_slices(all_image_paths) image_ds = path_ds.map(load_and_preprocess_image, num_parallel_calls=AUTOTUNE) label_ds = tf.data.Dataset.from_tensor_slices(tf.cast(all_image_labels, tf.int64))# image_ds 和 label_ds 可以組合一下 image_label_ds = tf.data.Dataset.zip((image_ds, label_ds))# 當然也可以直接兩個數組進行tf.data.Dataset ds = tf.data.Dataset.from_tensor_slices((all_image_paths, all_image_labels))# 元組被解壓縮到映射函數的位置參數中 def load_and_preprocess_from_path_label(path, label):return load_and_preprocess_image(path), labelimage_label_ds = ds.map(load_and_preprocess_from_path_label)# 對數據集進行設置就是 ds = image_label_ds.cache() ds = ds.apply(tf.data.experimental.shuffle_and_repeat(buffer_size=image_count)) ds = ds.batch(BATCH_SIZE).prefetch(buffer_size=AUTOTUNE)CSV
官方CSV,也就是EXCEl格式的文件讀取。看了官方的例子,發現英文版和中文版代碼都不是一致的,有點意思。
引包
import functoolsimport numpy as np import tensorflow as tf import tensorflow_datasets as tfds數據準備
下載數據,這個數據集是關于泰坦尼克號幸存者的名單信息。
TRAIN_DATA_URL = "https://storage.googleapis.com/tf-datasets/titanic/train.csv" TEST_DATA_URL = "https://storage.googleapis.com/tf-datasets/titanic/eval.csv"train_file_path = tf.keras.utils.get_file("train.csv", TRAIN_DATA_URL) test_file_path = tf.keras.utils.get_file("eval.csv", TEST_DATA_URL) # 讓 numpy 數據更易讀。 np.set_printoptions(precision=3, suppress=True)有了數據后,將數據導入到dataset 的構造函數中tf.data.experimental.make_csv_dataset
LABEL_COLUMN = 'survived' LABELS = [0, 1]def get_dataset(file_path):dataset = tf.data.experimental.make_csv_dataset(file_path,batch_size=12, # 為了示例更容易展示,手動設置較小的值label_name=LABEL_COLUMN,na_value="?",num_epochs=1,ignore_errors=True)return datasetraw_train_data = get_dataset(train_file_path) raw_test_data = get_dataset(test_file_path)打印下信息看看,看了下,是一個大字典,里面鍵值對對應著數組
examples, labels = next(iter(raw_train_data)) # 第一個批次 print("EXAMPLES: \n", examples, "\n") print("LABELS: \n", labels)結果
EXAMPLES: OrderedDict([ ('sex', <tf.Tensor: shape=(12,), dtype=string, numpy= array([b'male', b'male', b'female', b'male', b'male', b'male', b'male',b'female', b'male', b'female', b'male', b'female'], dtype=object)>), ('age', <tf.Tensor: shape=(12,), dtype=float32, numpy= array([25., 23., 28., 35., 28., 47., 35., 45., 19., 31., 29., 32.],dtype=float32)>), ('n_siblings_spouses', <tf.Tensor: shape=(12,), dtype=int32, numpy=array([0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0])>), ('parch', <tf.Tensor: shape=(12,), dtype=int32, numpy=array([0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0])>), ('fare', <tf.Tensor: shape=(12,), dtype=float32, numpy= array([ 13. , 63.358, 7.879, 512.329, 7.896, 9. , 7.125,164.867, 10.171, 113.275, 27.721, 13. ], dtype=float32)>), ('class', <tf.Tensor: shape=(12,), dtype=string, numpy= array([b'Second', b'First', b'Third', b'First', b'Third', b'Third',b'Third', b'First', b'Third', b'First', b'Second', b'Second'],dtype=object)>), ('deck', <tf.Tensor: shape=(12,), dtype=string, numpy= array([b'unknown', b'D', b'unknown', b'B', b'unknown', b'unknown',b'unknown', b'unknown', b'unknown', b'D', b'unknown', b'unknown'],dtype=object)>), ('embark_town', <tf.Tensor: shape=(12,), dtype=string, numpy= array([b'Southampton', b'Cherbourg', b'Queenstown', b'Cherbourg',b'Southampton', b'Southampton', b'Southampton', b'Southampton',b'Southampton', b'Cherbourg', b'Cherbourg', b'Southampton'],dtype=object)>), ('alone', <tf.Tensor: shape=(12,), dtype=string, numpy= array([b'y', b'n', b'y', b'y', b'y', b'y', b'y', b'n', b'y', b'n', b'n',b'y'], dtype=object)>)]) LABELS: tf.Tensor([0 1 1 1 0 0 0 1 0 1 0 1], shape=(12,), dtype=int32)數據預處理
離散的數據
tf.feature_column.indicator_column我的感覺就是可以把分類的列變成onehot的感覺,比如性別列下有男有女,那么就定義男(1,0),女就是(0,1)。
CATEGORIES = {'sex': ['male', 'female'],'class' : ['First', 'Second', 'Third'],'deck' : ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'],'embark_town' : ['Cherbourg', 'Southhampton', 'Queenstown'],'alone' : ['y', 'n'] }categorical_columns = [] for feature, vocab in CATEGORIES.items():cat_col = tf.feature_column.categorical_column_with_vocabulary_list(key=feature, vocabulary_list=vocab)categorical_columns.append(tf.feature_column.indicator_column(cat_col))連續的浮點數據
如果是浮點數據需要標準化,也就是歸一化,要不不同的列數值差的太遠了。
現在創建一個數值列的集合。tf.feature_columns.numeric_column API 會使用 normalizer_fn參數。在傳參的時候使用 functools.partial,functools.partial 由使用每個列的均值進行標準化的函數構成。
def process_continuous_data(mean, data):# 標準化數據data = tf.cast(data, tf.float32) * 1/(2*mean)return tf.reshape(data, [-1, 1])MEANS = {'age' : 29.631308,'n_siblings_spouses' : 0.545455,'parch' : 0.379585,'fare' : 34.385399 }numerical_columns = []for feature in MEANS.keys():num_col = tf.feature_column.numeric_column(feature, normalizer_fn=functools.partial(process_continuous_data, MEANS[feature]))numerical_columns.append(num_col)模型準備
預處理層
tf.keras.layers.DenseFeatures的作用就是將列的數據變成單個的Tensor
跑起來
train_data = raw_train_data.shuffle(500) test_data = raw_test_datamodel.fit(train_data, epochs=20)test_loss, test_accuracy = model.evaluate(test_data)print('\n\nTest Loss {}, Test Accuracy {}'.format(test_loss, test_accuracy))predictions = model.predict(test_data)# 顯示部分結果 for prediction, survived in zip(predictions[:10], list(test_data)[0][1][:10]):print("Predicted survival: {:.2%}".format(prediction[0])," | Actual outcome: ",("SURVIVED" if bool(survived) else "DIED"))Numpy
這個是Pytorch的老朋友了,相當熟悉了NumPy 。
引包
import numpy as np import tensorflow as tf數據準備
DATA_URL = 'https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz'path = tf.keras.utils.get_file('mnist.npz', DATA_URL) with np.load(path) as data:train_examples = data['x_train']train_labels = data['y_train']test_examples = data['x_test']test_labels = data['y_test']出來的數據格式為(6000,28,28),也是用tf.data.Dataset.from_tensor_slices來處理。
train_dataset = tf.data.Dataset.from_tensor_slices((train_examples, train_labels)) test_dataset = tf.data.Dataset.from_tensor_slices((test_examples, test_labels)) BATCH_SIZE = 64 SHUFFLE_BUFFER_SIZE = 100train_dataset = train_dataset.shuffle(SHUFFLE_BUFFER_SIZE).batch(BATCH_SIZE) test_dataset = test_dataset.batch(BATCH_SIZE)model = tf.keras.Sequential([tf.keras.layers.Flatten(input_shape=(28, 28)),tf.keras.layers.Dense(128, activation='relu'),tf.keras.layers.Dense(10) ])model.compile(optimizer=tf.keras.optimizers.RMSprop(),loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),metrics=['sparse_categorical_accuracy'])跑起來
model.fit(train_dataset, epochs=10)model.evaluate(test_dataset)數據格式比較規矩,就也還行。
pandas dataframes
pandas dataframes官方中文例子,就是pandas第三方庫來進行修改。
引包
import pandas as pd import tensorflow as tf數據準備
官網的鏈接不好使了,我替換成可以用的鏈接https://storage.googleapis.com/tf-datasets/titanic/train.csv
csv_file = tf.keras.utils.get_file('heart.csv', 'https://storage.googleapis.com/tf-datasets/titanic/train.csv') df = pd.read_csv(csv_file) print(df.head()) print(df.dtypes)打印信息
survived sex age ... deck embark_town alone 0 0 male 22.0 ... unknown Southampton n 1 1 female 38.0 ... C Cherbourg n 2 1 female 26.0 ... unknown Southampton y 3 1 female 35.0 ... C Southampton n 4 0 male 28.0 ... unknown Queenstown ysurvived int64 sex object age float64 n_siblings_spouses int64 parch int64 fare float64 class object deck object embark_town object alone object里面有一些字符串的數據,我們將其變為離散數值。
df['sex'] = pd.Categorical(df['sex']) df['sex'] = df.sex.cat.codes再打印依次
survived sex age n_siblings_spouses ... class deck embark_town alone 0 0 1 22.0 1 ... Third unknown Southampton n 1 1 0 38.0 1 ... First C Cherbourg n 2 1 0 26.0 0 ... Third unknown Southampton y 3 1 0 35.0 1 ... First C Southampton n 4 0 1 28.0 0 ... Third unknown Queenstown y果然性別(sex)一列變成數字了,將其他的列也變一下,并且把class這個列刪除掉,class這個名字比較敏感。
df['deck'] = pd.Categorical(df['deck']) df['deck'] = df.deck.cat.codesdf['embark_town'] = pd.Categorical(df['embark_town']) df['embark_town'] = df.embark_town.cat.codesdf['alone'] = pd.Categorical(df['alone']) df['alone'] = df.alone.cat.codes df.drop('class', axis=1, inplace=True)print(df.head())讀取數據
將alone字段設置為要預測的值,df.pop()選哪個哪個就是標簽值,只能選一次。進入到tf.data.Dataset.from_tensor_slices函數中,打印的時候采用take這個函數。
alone = df.pop('survived') dataset = tf.data.Dataset.from_tensor_slices((df.values, alone.values)) for feat, targ in dataset.take(5):print ('Features: {}, Target: {}'.format(feat, targ))隨機讀取一下,并設定批次。PS. 這就沒有設置repeat和cache。
批次為一,shuffle的值是整體數據長度。
模型準備并跑起來
def get_compiled_model():model = tf.keras.Sequential([tf.keras.layers.Dense(10, activation='relu'),tf.keras.layers.Dense(10, activation='relu'),tf.keras.layers.Dense(1, activation='sigmoid')])model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])return modelmodel = get_compiled_model() model.fit(train_dataset, epochs=15)代替特征列
也可以采用字典的方式,將數據傳輸到模型中。
鍵值對的值采用tf.keras.layers.Input(shape=(), name=key)函數做的。
效果是一樣的
({'survived': <tf.Tensor: shape=(16,), dtype=int32, numpy=array([0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1])>, 'sex': <tf.Tensor: shape=(16,), dtype=int32, numpy=array([1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0])>, 'age': <tf.Tensor: shape=(16,), dtype=float32, numpy=array([22., 38., 26., 35., 28., 2., 27., 14., 4., 20., 39., 14., 2., 28., 31., 28.], dtype=float32)>, 'n_siblings_spouses': <tf.Tensor: shape=(16,), dtype=int32, numpy=array([1, 1, 0, 1, 0, 3, 0, 1, 1, 0, 1, 0, 4, 0, 1, 0])>, 'parch': <tf.Tensor: shape=(16,), dtype=int32, numpy=array([0, 0, 0, 0, 0, 1, 2, 0, 1, 0, 5, 0, 1, 0, 0, 0])>, 'fare': <tf.Tensor: shape=(16,), dtype=float32, numpy=array([ 7.25 , 71.2833, 7.925 , 53.1 , 8.4583, 21.075 , 11.1333, 30.0708, 16.7 , 8.05 , 31.275 , 7.8542, 29.125 , 13. , 18. , 7.225 ], dtype=float32)>, 'deck': <tf.Tensor: shape=(16,), dtype=int32, numpy=array([7, 2, 7, 2, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7])>, 'embark_town': <tf.Tensor: shape=(16,), dtype=int32, numpy=array([2, 0, 2, 2, 1, 2, 2, 0, 2, 2, 2, 2, 1, 2, 2, 0])>}, <tf.Tensor: shape=(16,), dtype=int8, numpy=array([0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1], dtype=int8)>)TFRecord 和 tf.Example
TFRecord 和 tf.Example官方例子
為了高效地讀取數據,比較有幫助的一種做法是對數據進行序列化并將其存儲在一組可線性讀取的文件(每個文件100-200MB)中。這尤其適用于通過網絡進行流式傳輸的數據。這種做法對緩沖任何數據預處理也十分有用。
TFRecord 格式是一種用于存儲二進制記錄序列的簡單格式。
協議緩沖區是一個跨平臺、跨語言的庫,用于高效地序列化結構化數據。
協議消息由 .proto 文件定義,這通常是了解消息類型最簡單的方法。
tf.Example 消息(或 protobuf)是一種靈活的消息類型,表示 {“string”: value} 映射。它專為TensorFlow 而設計,并被用于 TFX 等高級 API。
本筆記本將演示如何創建、解析和使用 tf.Example 消息,以及如何在 .tfrecord 文件之間對 tf.Example消息進行序列化、寫入和讀取。
注:這些結構雖然有用,但并不是強制的。您無需轉換現有代碼即可使用 TFRecord,除非您正在使用 tf.data且讀取數據仍是訓練的瓶頸。有關數據集性能的提示,請參閱數據輸入流水線性能。
我的理解就是跟我們從網上下載文件一樣,采用流的方式,一點一點下載,這樣如果斷了,還可以接著下,不必從頭開始。數據也是一樣的。
這個先了解
文本數據
文本數據,了解下tf.data.TextLineDataset的方法。
原文件中的一行為一個樣本,這適用于大多數的基于行的文本數據
引包
import tensorflow as tfimport tensorflow_datasets as tfds import os數據準備
下載規整好的數據。
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 = tf.keras.utils.get_file(name, origin=DIRECTORY_URL+name)parent_dir = os.path.dirname(text_dir)數據變成 tf.data.TextLineDataset
將數據壓進tf.data.Dataset.map,用tf.data.TextLineDataset讀取數據,
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(os.path.join(parent_dir, file_name))labeled_dataset = lines_dataset.map(lambda ex: labeler(ex, i))labeled_data_sets.append(labeled_dataset) # 把這三個數據集變成一個,再混淆掉 BUFFER_SIZE = 50000 BATCH_SIZE = 64 TAKE_SIZE = 5000all_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)來看一眼里面的數據是什么樣子的
for ex in all_labeled_data.take(5):print(ex)numpy就是每個Tensor 值。
(<tf.Tensor: shape=(), dtype=string, numpy=b"\xef\xbb\xbfAchilles sing, O Goddess! Peleus' son;">, <tf.Tensor: shape=(), dtype=int64, numpy=0>) (<tf.Tensor: shape=(), dtype=string, numpy=b'His wrath pernicious, who ten thousand woes'>, <tf.Tensor: shape=(), dtype=int64, numpy=0>) (<tf.Tensor: shape=(), dtype=string, numpy=b"Caused to Achaia's host, sent many a soul">, <tf.Tensor: shape=(), dtype=int64, numpy=0>) (<tf.Tensor: shape=(), dtype=string, numpy=b'Illustrious into Ades premature,'>, <tf.Tensor: shape=(), dtype=int64, numpy=0>) (<tf.Tensor: shape=(), dtype=string, numpy=b'And Heroes gave (so stood the will of Jove)'>, <tf.Tensor: shape=(), dtype=int64, numpy=0>)數據變為數字變量
有了文字,那就把文字變成數字,方便計算機計算,盲猜是onehot或者向量嵌入。
官網例子是tfds.features.text.Tokenizer()需要改成tfds.deprecated.text.Tokenizer(),這個庫更新的也太快了吧,官網例子都跟不上。
官網的例子tfds.features.text.TokenTextEncoder需要改成tfds.deprecated.text.TokenTextEncoder,采用tfds.deprecated.text.TokenTextEncoder將樣本進行編碼。PS.應該現在有更好的函數吧,要不也不能廢棄。
encoder = tfds.deprecated.text.TokenTextEncoder(vocabulary_set) example_text = next(iter(all_labeled_data))[0].numpy() print(example_text) # b'With slanted shields, the Greeks; yet Hector still' encoded_example = encoder.encode(example_text) print(encoded_example) # [8132, 15145, 4866, 10461, 7732, 465, 17108, 13725]Tensorflow的思想總是在用到的時候再做處理。我寫PyTorch的時候總是喜歡把數據都處理的特別穩妥后再處理。
def encode(text_tensor, label):encoded_text = encoder.encode(text_tensor.numpy())return encoded_text, labeldef encode_map_fn(text, label):# py_func doesn't set the shape of the returned tensors.encoded_text, label = tf.py_function(encode, inp=[text, label], Tout=(tf.int64, tf.int64))# `tf.data.Datasets` work best if all components have a shape set# so set the shapes manually: encoded_text.set_shape([None])label.set_shape([])return encoded_text, labelall_encoded_data = all_labeled_data.map(encode_map_fn)劃分訓練測試集
tf.data.Dataset.take 和 tf.data.Dataset.skip可以看作是從tf.data.Dataset拿多少數據出來以及略去多少剩下的全要。還是tf.data.Dataset.padded_batch好用,全都自動化,不用自己去寫補全代碼,直接就是自動填充。因為文本不像是圖片,長短不一,也不可以去拉伸什么的,只能在后面補零成相同的大小。
train_data = all_encoded_data.skip(TAKE_SIZE).shuffle(BUFFER_SIZE) train_data = train_data.padded_batch(BATCH_SIZE)test_data = all_encoded_data.take(TAKE_SIZE) test_data = test_data.padded_batch(BATCH_SIZE)看下數據奧
# 這個是一個批次的集合 sample_text, sample_labels = next(iter(test_data)) # 從批次里選第一個看看 print(sample_text[0], sample_labels[0])結果,可以看到后面都是補了零
(<tf.Tensor: shape=(15,), dtype=int64, numpy=array([ 8132, 15145, 4866, 10461, 7732, 465, 17108, 13725, 0,0, 0, 0, 0, 0, 0], dtype=int64)>,<tf.Tensor: shape=(), dtype=int64, numpy=1>)零也是一個token,那么詞匯表的大小就要加一了
vocab_size += 1模型準備
果然還是用向量嵌入的方式,接下來就是LSTM
model = tf.keras.Sequential() model.add(tf.keras.layers.Embedding(vocab_size, 64)) model.add(tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64)))# 一個或多個緊密連接的層 # 編輯 `for` 行的列表去檢測層的大小 for units in [64, 64]:model.add(tf.keras.layers.Dense(units, activation='relu'))# 輸出層。第一個參數是標簽個數,激活函數是softmax。 model.add(tf.keras.layers.Dense(3, activation='softmax')) # 一般softmax用sparse_categorical_crossentropy作損失函數。 model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])跑起來
model.fit(train_data, epochs=3, validation_data=test_data)eval_loss, eval_acc = model.evaluate(test_data)print('\nEval loss: {}, Eval accuracy: {}'.format(eval_loss, eval_acc))結果
Eval loss: 0.38248714804649353, Eval accuracy: 0.8285999894142151總結
Tensorflow真的強大,但是前提要熟悉它的一些API。
總結
以上是生活随笔為你收集整理的Tensorflow2.0学习-加载和预处理数据 (七)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (二)Cypher语言常用方法举例
- 下一篇: 前后端分离的项目部署到tomcat_如何