3. 数据预处理

3. 数据预处理#

Open In Colab

在第二章中,我们探索了用于模型训练的数据并检查了数据特征。在第3章中,我们将检查如何预处理时间序列数据。

为了将时间序列数据转换为监督学习问题,必须将数据处理成一对要预测的目标变量和用于预测的输入变量。此外,为了稳定地训练深度学习模型,需要统一数据的规模。在第 3.1 节中,我们将研究将确诊的冠状病毒数据转换为用于监督学习的数据的过程,在第 3.2 节中,我们将检查如何扩展数据。

3.1 构建监督学习数据#

对于数据预处理实践,我们将使用 2.1 节中所示的代码加载数据。

!git clone https://github.com/Pseudo-Lab/Tutorial-Book-Utils
!python Tutorial-Book-Utils/PL_data_loader.py --data COVIDTimeSeries
!unzip -q COVIDTimeSeries.zip
'git' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
python: can't open file 'D:\3000-code\deeplearning\DeepLearning2023\Deeplearning\chapters\chpt4\Tutorial-Book-Utils\PL_data_loader.py': [Errno 2] No such file or directory
'unzip' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

使用2.3节中的代码,daily_cases我们将计算韩国每天的确诊病例数据。

import pandas as pd
confirmed = pd.read_csv('time_series_covid19_confirmed_global.csv')
confirmed[confirmed['Country/Region']=='Korea, South']
korea = confirmed[confirmed['Country/Region']=='Korea, South'].iloc[:,4:].T
korea.index = pd.to_datetime(korea.index)
daily_cases = korea.diff().fillna(korea.iloc[0]).astype('int')
daily_cases
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[2], line 2
      1 import pandas as pd
----> 2 confirmed = pd.read_csv('time_series_covid19_confirmed_global.csv')
      3 confirmed[confirmed['Country/Region']=='Korea, South']
      4 korea = confirmed[confirmed['Country/Region']=='Korea, South'].iloc[:,4:].T

File D:\Program Files\Python39\lib\site-packages\pandas\io\parsers\readers.py:1026, in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options, dtype_backend)
   1013 kwds_defaults = _refine_defaults_read(
   1014     dialect,
   1015     delimiter,
   (...)
   1022     dtype_backend=dtype_backend,
   1023 )
   1024 kwds.update(kwds_defaults)
-> 1026 return _read(filepath_or_buffer, kwds)

File D:\Program Files\Python39\lib\site-packages\pandas\io\parsers\readers.py:620, in _read(filepath_or_buffer, kwds)
    617 _validate_names(kwds.get("names", None))
    619 # Create the parser.
--> 620 parser = TextFileReader(filepath_or_buffer, **kwds)
    622 if chunksize or iterator:
    623     return parser

File D:\Program Files\Python39\lib\site-packages\pandas\io\parsers\readers.py:1620, in TextFileReader.__init__(self, f, engine, **kwds)
   1617     self.options["has_index_names"] = kwds["has_index_names"]
   1619 self.handles: IOHandles | None = None
-> 1620 self._engine = self._make_engine(f, self.engine)

File D:\Program Files\Python39\lib\site-packages\pandas\io\parsers\readers.py:1880, in TextFileReader._make_engine(self, f, engine)
   1878     if "b" not in mode:
   1879         mode += "b"
-> 1880 self.handles = get_handle(
   1881     f,
   1882     mode,
   1883     encoding=self.options.get("encoding", None),
   1884     compression=self.options.get("compression", None),
   1885     memory_map=self.options.get("memory_map", False),
   1886     is_text=is_text,
   1887     errors=self.options.get("encoding_errors", "strict"),
   1888     storage_options=self.options.get("storage_options", None),
   1889 )
   1890 assert self.handles is not None
   1891 f = self.handles.handle

File D:\Program Files\Python39\lib\site-packages\pandas\io\common.py:873, in get_handle(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)
    868 elif isinstance(handle, str):
    869     # Check whether the filename is to be opened in binary mode.
    870     # Binary mode does not support 'encoding' and 'newline'.
    871     if ioargs.encoding and "b" not in ioargs.mode:
    872         # Encoding
--> 873         handle = open(
    874             handle,
    875             ioargs.mode,
    876             encoding=ioargs.encoding,
    877             errors=errors,
    878             newline="",
    879         )
    880     else:
    881         # Binary mode
    882         handle = open(handle, ioargs.mode)

FileNotFoundError: [Errno 2] No such file or directory: 'time_series_covid19_confirmed_global.csv'

为了使上述时间序列数据能够被模型用于监督学习,必须将数据处理成输入变量和目标变量对。在时间序列问题中,此类数据也称为序列数据。为了将其处理成序列数据,必须首先定义序列长度。序列长度决定了有多少过去的数据可以预测未来。例如,如果序列长度为5t 过去来预测某个时间点 \(t-1\), \(t-2\), \(t-3\), \(t-4\), \(t-5\) 您将利用该时间点的数据。像这样 \(t-k\) 从터 \(t-1\) 数据高达 \(t\) 预测时间称为一步预测任务。 下面定义的函数create_sequences将大小为N的时间序列数据转换为N-seq_length的监督学习数据,

  • 图3-1 时间序列数据转换流程

import numpy as np

def create_sequences(data, seq_length):
    xs = []
    ys = []
    for i in range(len(data)-seq_length):
        x = data.iloc[i:(i+seq_length)]
        y = data.iloc[i+seq_length]
        xs.append(x)
        ys.append(y)
    return np.array(xs), np.array(ys)

seq_length = 5
X, y = create_sequences(daily_cases, seq_length)

seq_length通过定义 5 并将create_sequences函数应用daily_cases到 ,可以看到总共构建了 327 个监督学习数据。

X.shape, y.shape
((327, 5, 1), (327, 1))

我们将构建的数据分为学习数据、验证数据和测试数据。我们将以 8:1:1 的比例分离数据。 327 的 80% 大约为 261,因此我们将使用前 261 个数据进行训练,接下来的 33 个数据进行验证,最后 33 个数据进行测试。

train_size = int(327 * 0.8)
print(train_size)
261
X_train, y_train = X[:train_size], y[:train_size]
X_val, y_val = X[train_size:train_size+33], y[train_size:train_size+33]
X_test, y_test = X[train_size+33:], y[train_size+33:]
print(X_train.shape, X_val.shape, X_test.shape)
print(y_train.shape, y_val.shape, y_test.shape)
(261, 5, 1) (33, 5, 1) (33, 5, 1)
(261, 1) (33, 1) (33, 1)

3.2 数据缩放#

在本节中,我们将执行数据缩放。我们将执行 MinMax 缩放,将数据范围转换为 0 到 1 之间。 MinMax 缩放计算数据集的最小值和最大值,并使用以下公式应用它们

\(x_{scaled} = \displaystyle\frac{x - x_{min}}{x_{max} - x_{min}}\)

扩展时要记住的一件事是,您必须使用训练数据的统计数据来扩展训练、验证和测试数据集。由于在学习模型时不应输入测试数据的信息,因此使用训练数据的统计量对训练数据进行缩放。由于模型是使用根据训练数据的统计数据缩放的数据来学习的,因此用于未来模型性能评估的测试数据输入也根据训练数据的统计数据缩放。同样,验证数据必须经过与测试数据相同的预处理过程,因此它会根据训练数据的统计数据进行缩放。

要应用 MinMax 缩放,X_train我们将找到数据的最小值和最大值。

MIN = X_train.min()
MAX = X_train.max()
print(MIN, MAX)
0 851

最小值为 0,最大值为 851。接下来,我们将定义 MinMax 缩放函数。

def MinMaxScale(array, min, max):

    return (array - min) / (max - min)

MinMaxScale我们将使用函数进行扩展。

X_train = MinMaxScale(X_train, MIN, MAX)
y_train = MinMaxScale(y_train, MIN, MAX)
X_val = MinMaxScale(X_val, MIN, MAX)
y_val = MinMaxScale(y_val, MIN, MAX)
X_test = MinMaxScale(X_test, MIN, MAX)
y_test = MinMaxScale(y_test, MIN, MAX)

接下来,我们将np.array数据类型转换为要输入到 PyTorch 模型中的类型。torch.Tensor首先,我们定义一个转换数据类型的函数。

import torch

def make_Tensor(array):
    return torch.from_numpy(array).float()

make_Tensor我们将使用函数来转换数据类型。

X_train = make_Tensor(X_train)
y_train = make_Tensor(y_train)
X_val = make_Tensor(X_val)
y_val = make_Tensor(y_val)
X_test = make_Tensor(X_test)
y_test = make_Tensor(y_test)

到目前为止,我们已经了解了如何将时间序列数据转换为用于监督学习的数据以及如何缩放数据。在下一章中,我们将使用构建的数据构建冠状病毒确诊病例的预测模型。