在TensorFlow中使用sample_weight

时间:2020-09-04 15:53:04

标签: time-series tensorflow2.0

我很难适应缺少标签(不是要素)的时间序列。

我要解决的问题是:患者每天服用一或两片(X值)。病人有时可以监测他们血液中的药物浓度(标签)。病人每隔几天(例如2到14之间)测量一次此浓度值。因此,时间序列将由X(每天服用的药片数量)和标签(每几天)组成。我的模型的目的是根据服用药片的历史来预测药物浓度。

在Keras中,我尝试将LSTM与.compile中的sample_weight_mode='temporal'选项和.fit中的sample_weight选项一起使用(如StackExchange上的建议)。不幸的是,拟合似乎无法正确应用权重。

目前,我正在处理玩具数据集,其中标签是时间值的正弦函数。

然后我随机引入10%的缺失值。我将这些值设置为-1只是为了将其标记为无效。

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import tensorflow as tf
from datetime import datetime
from random import random

#Simulate Time Series on 3000 days
time_ = np.arange(0, 3000, 1)/10
labels = 1 + np.sin(time_) + time_*0.01

# Simulate 10% of missing labels. Mark them with -1
ind_nan=np.random.choice(len(labels), int(len(labels)*0.1), replace=False)
labels[ind_nan]=-1

#Create sample_weight, an array of 1's with 0 on the missing labels
sample_weight=np.ones(len(labels))
sample_weight[ind_nan]=0
#Create dataframes with data and weights
df = pd.DataFrame({'labels': labels})
sample_weight_df = pd.DataFrame(dict(sample_weight=sample_weight))

#Train/Test Split
train_size = int(len(df) * 0.8)
train_df, test_df = df.iloc[:train_size], df.iloc[train_size:]
train_sample_weight, test_sample_weight = sample_weight_df.iloc[:train_size], df.iloc[train_size:]
print(len(train_df), len(test_df))  #2400 600
print(len(train_sample_weight), len(test_sample_weight)) #2400 600

我正在使用this tutorial中的create_dataset method

def create_dataset(X, y, time_steps=1):
    #From this tutorial https://www.curiousily.com/posts/time-series-forecasting-with-lstms-using-tensorflow-2-and-keras-in-python/
    Xs, ys = [], []
    for i in range(len(X) - time_steps):
        v = X.iloc[i:i+time_steps].values
        Xs.append(v)
        ys.append(y.iloc[i+time_steps])
    return np.array(Xs), np.array(ys)

# reshape data and weights to [samples, time_steps, n_features]
X_train, y_train = create_dataset(train_df, train_df.labels, 10)
X_test, y_test = create_dataset(test_df, test_df.labels, 10)
sample_weight_train, _ = create_dataset(train_sample_weight, sample_weight_df.sample_weight, 10)
print(X_train.shape, y_train.shape, sample_weight_train.shape) #(2390, 10, 1) (2390,) (2390, 10, 1)

火车数据和重量看起来不错:

#Quickly check that the weight array is 0 where X_train is -1 i.e. missing
X_train[17,:,0]
sample_weight_train[17,:,0]

这是模型。我在.fit中设置了shuffle=False,因为显然validation data is never shuffled

model = tf.keras.Sequential()
model.add(tf.keras.layers.LSTM(
  units=128,
  input_shape=(X_train.shape[1], X_train.shape[2])
))
model.add(tf.keras.layers.Dense(units=1))
model.compile(
  loss='mean_squared_error',
  optimizer=tf.keras.optimizers.Adam(0.001),
    sample_weight_mode='temporal'   #Weights
)


history = model.fit(
    X_train, y_train,
    epochs=30,
    batch_size=16,
    validation_split=0.1, #last 10% of the data
    verbose=0,
    shuffle=False,
    sample_weight=sample_weight_train #(samples, sequence_length)
)

#Predict on test
y_pred = model.predict(X_test)
#Plot
fig=plt.figure(figsize=(18,10))
plt.scatter(time_[0:train_size], train_df, color='k', label='train')
plt.scatter(time_[train_size:], test_df, color='b', label='test')
plt.scatter(time_[train_size+10:], y_pred, color='r', label='y_pred')
plt.legend();
plt.xlim([200,300])

当我没有任何-1 /缺失标签时LSTM可以很容易地适应这个时间序列(未显示,只需在上面的random.choice中使用0而不是0.1来运行此代码)。但是,如果缺少10%的标签,则无法进行预测。该模型似乎试图拟合丢失的标签/ -1。

为什么砝码不能正常工作?

prediction

0 个答案:

没有答案