序列數據(具有時間依賴性的數據)在業務中非常常見,從信用卡交易到醫療保健記錄再到股票市場價格。 但是,隱私法規限制並極大地減慢了對研發至關重要的有用數據的訪問。 這就產生了對具有高度代表性但又完全私有的合成順序數據的需求,這至少可以說是具有挑戰性的。
生成合成時間序列和順序數據要比表格數據更具挑戰性,在表格數據中,通常將與一個人有關的所有信息存儲在一行中。 在順序數據中,信息可以分布在許多行中,例如信用卡交易,並且保留行(事件)和列之間的相關性(變量是關鍵)。 此外,序列的長度是可變的。 有些案例可能只包含少量交易,而其他案例則可能包含數千筆交易。
序列數據和時間序列的生成模型已經得到了廣泛的研究,但是,許多此類努力導致綜合數據質量相對較差且靈活性較低。 在許多情況下,模型被設計為特定於每個問題,因此需要詳細的領域知識。
在本文中,我們描述並應用了一種最新的強大方法的擴展版本,以生成合成順序數據DoppelGANger。 它是基於生成對抗網絡(GAN)的框架,具有一些創新,使生成複雜順序數據集的合成版本成為可能。
我們通過引入兩項創新來構建這項工作:
1. 一種學習策略,可加快GAN的收斂速度並避免模式崩潰。
1. 鑑別器中經過精心設計的噪聲可使用差異會計處理策略的改進版本來提高模型的穩定性,從而使過程具有不同的私有性而不會降低數據質量。
用於時序數據生成的大多數模型都使用以下方法之一:
動態平穩過程通過將時間序列中的每個點表示為確定性過程的總和(加上一些噪聲)而起作用。 這是使用自舉等技術對時間序列進行建模的一種廣泛使用的方法。 但是,必須納入一些長期依賴性的先驗知識,例如循環模式,以約束確定性過程。 這使得很難為具有複雜,未知相關性的數據集建模。
馬爾可夫模型是一種通過將系統動力學表示為條件概率分布來對分類時間序列建模的流行方法。 諸如隱馬爾可夫模型的變體也已用於對時間序列的分布進行建模。 這種方法的問題在於它無法捕獲長期的複雜依賴關係。
自回歸(AR)模型是動態平穩過程,其中序列中的每個點都表示為前n個點的函數。非線性AR模型(如ARIMA)非常強大。像馬爾可夫模型那樣的AR模型存在保真度問題-它們產生的簡單模型無法捕獲複雜的時間相關性。
遞歸神經網絡(RNN)最近已用於深度學習中的時間序列建模。像自回歸模型和馬爾可夫模型一樣,RNN使用以前時間步長的滑動窗口來確定下一個時間點。 RNN還存儲一個內部狀態變量,該變量捕獲時間序列的整個歷史記錄。像長短期記憶網絡(LTSM)一樣,RNN在學習時間序列數據的判別模型方面也取得了巨大的成功,該模型可預測以樣本為條件的標籤。但是,RNN無法學習某些簡單的時間序列分布。
基於GAN的方法或生成對抗網絡模型已經成為一種流行的技術,用於生成或擴充數據集,尤其是圖像和視頻。但是,GAN在網絡數據中保真度較差,網絡數據既具有複雜的時間相關性,又具有混合的離散連續數據類型。儘管存在基於GAN的時間序列生成(例如,用於醫療時間序列),但此類技術無法處理更複雜的數據,這些數據在長序列上顯示出較差的自相關評分,同時容易出現模式崩潰。這是由於以下事實:數據分布是重尾且長度可變的。這似乎在很大程度上影響GAN。
在本節中,我將探索最近的模型以生成綜合順序數據DoppelGANger。 我將使用基於GAN的此模型以及由循環單位組成的生成器,使用兩個數據集生成交易數據的綜合版本:銀行交易和道路交通。 我們使用了對DoppelGANger模型的修改,以解決順序數據生成模型的局限性。
由於以下問題,傳統的生成對抗網絡或GAN難以對順序數據進行建模:
1. 它們沒有捕獲時間特徵及其相關(不變)屬性之間的複雜關聯:例如,根據所有者的特徵(年齡,收入等),交易中的信用卡模式非常不同。
1. 時間序列內的長期相關性,例如晝夜模式:這些相關性與圖像中的相關性在質量上有很大不同,圖像具有固定的尺寸,不需要逐像素生成。
DoppelGANger結合了一些創新的想法,例如:
使用兩個網絡(一個多層感知機 MLP和一個遞歸網絡)捕獲時間依賴性
分離歸因生成,以更好地捕獲時間序列及其屬性(例如用戶的年齡,位置和性別)之間的相關性
批量生成-生成長序列的小批量堆疊
解耦歸一化-將歸一化因子添加到生成器以限制特徵範圍
DoppelGANger將屬性的生成與時間序列解耦,同時在每個時間步將屬性饋送到時間序列生成器。 這與傳統方法相反,在傳統方法中,屬性和特徵是共同生成的。
DoppelGANger的條件生成體系結構還提供了更改屬性分布和對屬性進行條件調整的靈活性。 這也有助於隱藏屬性分布,從而增加隱私。
DoppelGANger模型還具有生成以數據屬性為條件的數據特徵的優勢。
圖1:原始DoppelGANger模型的示意圖,兩個生成器塊和兩個鑑別器。
該模型的另一個巧妙特徵是它如何處理極端事件,這是一個非常具有挑戰性的問題。順序數據在樣本中具有廣泛的功能值並不少見-有些產品可能有成千上萬筆交易,而另一些則只有幾筆。對於GAN來說,這是有問題的,因為它肯定是模式崩潰的秘訣-樣本將僅包含最常見的項目,而忽略罕見事件。對於圖像-幾乎所有工作都集中在GAN上-這不是問題,因為分布很平滑。這就是為什麼DoppelGANger的作者提出了一種創新的方式來處理這些情況:自動歸一化。它包括在訓練之前對數據特徵進行歸一化,並將特徵的最小和最大範圍添加為每個樣本的兩個附加屬性。
在生成的數據中,這兩個屬性通常會將要素縮放回現實範圍。這分三個步驟完成:
· 使用多層感知器(MLP)生成器生成屬性。
· 將生成的屬性作為輸入,使用另一個MLP生成兩個"偽"(最大/最小)屬性。
· 將生成的真實和假屬性作為輸入,生成要素。
首先,我們在銀行交易數據集上評估了DoppelGANger。 用於訓練的數據是合成的,因此我們知道真實的分布,可以在這裡訪問。 我們的目的是證明該模型能夠學習數據中的時間依賴性。
如何準備數據?
圖2:作為一組屬性和長度不同的特徵處理的數據的示意圖。
我們假設順序數據由一組最大長度為Lmax的序列組成-在本例中,我們認為Lmax =100。每個序列都包含一組屬性A(固定數量)和特徵F(交易)。 在我們的例子中,唯一的屬性是初始銀行餘額,其特徵是:交易金額(正數或負數)以及兩個描述交易的其他類別:標誌和描述。
要運行模型,我們需要三個NumPy數組:
· data_feature:訓練功能,採用NumPy float32數組格式。 大小為[(訓練樣本數)x(最大長度)x(特徵的總尺寸)]。 分類特徵通過一鍵編碼存儲。
· data_attribute:訓練屬性,為NumPy float32數組格式。 大小為[(訓練樣本數)x(屬性的總維數)]。
· datagenflag:一組標誌,指示功能的激活。 大小為[(訓練樣本數)x(最大長度)]。
另外,我們需要一個Output類的對象列表,其中包含每個變量,規範化和基數的數據類型。 在這種情況下,它是:
data_feature_outputs = [output.Output(type_=OutputType.CONTINUOUS,dim=1,normalization=Normalization.ZERO_ONE,is_gen_flag=False), # time intervals between transactions (Dif) output.Output(type_=OutputType.DISCRETE,dim=20,is_gen_flag=False), # binarized Amount output.Output(type_=OutputType.DISCRETE,dim=5,is_gen_flag=False),# Flagoutput.Output(type_=OutputType.DISCRETE,dim=44,is_gen_flag=False) # Description ]
列表的第一個元素是事件Dif之間的時間間隔,其後是經過1個熱編碼的交易值(金額),然後是標誌,第四個元素是交易描述。 所有gen_flags都設置為False,因為它是一個內部標誌,以後可以由模型本身進行修改。
該屬性被編碼為介於-1和1之間的歸一化連續變量,以解決負餘額問題:
data_attribute_outputs = [output.Output(type_=OutputType.CONTINUOUS,dim=1,normalization=Normalization.MINUSONE_ONE,is_gen_flag=False)]
此模擬中使用的唯一屬性是初始餘額。 每個步驟的餘額只需添加相應的交易金額即可更新。
我們使用Hazy處理器對每個序列進行預處理,並以正確的格式對其進行整形。
n_bins = 20processor_dict = { "by_type": { "float": { "processor": "FloatToOneHot", #FloatToBin" "kwargs": {"n_bins": n_bins} }, "int": { "processor": "IntToFloat", "kwargs": {"n_bins": n_bins} }, "category": { "processor": "CatToOneHot", }, "datetime": { "processor": "DtToFloat", } } }from hazy_trainer.processing import HazyProcessorprocessor = HazyProcessor(processor_dict)
現在,我們將讀取數據並使用formatdata函數對其進行處理。 輔助變量categoryn和category_cum分別存儲變量的基數和基數的累積和。
data=pd.read_csv('data.csv',nrows=100000) # read the datacategorical = ['Amount','Flag','Description'] continuous =['Balance','Dif']cols = categorical + continuousprocessor = HazyProcessor(processor_dict) #call Hazy processorprocessor.setup_df(data[cols]) # setup the processorcategories_n = [] # Number of categories in each categorical variablefor cat in categorical: categories_n.append(len(processor.column_to_columns[cat]['process']))categories_cum = list(np.cumsum(categories_n)) # Cumulative sum of number of categorical variablescategories_cum = [x for x in categories_cum] # We take one out because they will be indexescategories_cum = [0] + categories_cumdef format_data(data, cols, nsequences=1000, Lmax=100, cardinality=70):''' cols is a list of columns to be processednsequences number of sequences to use for training Lmax is the maximum sequence length Cardinality shape of sequences''' idd=list(accenture.Account_id.unique()) # unique account ids data.Date = pd.to_datetime(data.Date) # format date # dummy to normalize the processors data['Dif']=np.random.randint(0,30*24*3600,size=accenture.shape[0]) data_all = np.zeros((nsequences,Lmax,Cardinality)) data_attribut=np.zeros((nsequences)) data_gen_flag=np.zeros((nsequences,Lmax)) real_df = pd.DataFrame() for i,ids in enumerate(idd[:nsequences]): user = data[data.Account_id==ids] user=user.sort_values(by='Date') user['Dif']=user.Date.diff(1).iloc[1:] user['Dif']=user['Dif'].dt.seconds user = user[cols] real_df=pd.concat([real_df,user]) processed_df = processor.process_df(user) Data_attribut[i] = processed_df['Balance'].values[0] processed_array = np.asarray(processed_df.iloc[:,1:) data_gen_flag[i,:len(user)]=1 data_all[i,:len(user),:]=processed_arrayreturn data_all, data_attribut, data_gen_flag
數據
數據包含大約1000萬筆銀行交易,我們將僅使用其中包含5,000個唯一帳戶的100,000個樣本,每個帳戶平均20個交易。 我們考慮以下領域:
1. 交易日期
1. 交易金額
1. 平衡
1. 交易標記(5級)
1. 描述(44級)
以下是所用數據的標題:
表1:銀行交易數據樣本
如前所述,時間信息將被建模為兩個連續事務之間的時間差(以秒為單位)。
圖3:不同描述的交易直方圖按收入和支出分開。
圖4:不同時間分布的交易熱圖。
圖5:交易金額的分布。
圖6:初始餘額的分布。 請注意,由於透支,某些帳戶的初始餘額為負。
圖7:一個月內的交易數量-收入和支出。 請注意,收入有非常明顯的峰值。 綜合數據必須捕獲這些峰
我們使用以下參數僅運行了100個輪次的代碼:
import sysimport ossys.path.append("..")import matplotlib.pyplot as pltfrom gan import outputsys.modules["output"] = outputimport numpy as npimport pickleimport pandas as pdfrom gan.doppelganger import DoppelGANgerfrom gan.load_data import load_datafrom gan.network import DoppelGANgerGenerator, Discriminator, AttrDiscriminatorfrom gan.output import Output, OutputType, Normalizationimport tensorflow as tffrom gan.network import DoppelGANgerGenerator, Discriminator, \ RNNInitialStateType, AttrDiscriminatorfrom gan.util import add_gen_flag, normalize_per_sample, \ renormalize_per_samplesample_len = 10epoch = 100batch_size = 20d_rounds = 2g_rounds = 1d_gp_coe = 10.0attr_d_gp_coe = 10.0g_attr_d_coe = 1.0
請注意,生成器由具有softmax激活函數(用於分類輸入)和線性激活(用於連續變量)的層列表組成。 生成器和鑑別器均使用Adam算法以指定的學習速率和動量進行了優化。
現在,我們準備數據以供網絡使用。 realattributemask是一個True / False列表,其長度與屬性數相同。 如果屬性為(max-min)/ 2或(max + min)/ 2,則為False;否則為false。 否則為True。首先我們實例化生成器和鑑別器:
# create the necessary input arraysdata_all, data_attribut, data_gen_flag = format_data(data,cols)# normalise data(data_feature, data_attribute, data_attribute_outputs, real_attribute_mask) = normalize_per_sample( data_all, data_attribut, data_feature_outputs, data_attribute_outputs)# add generation flag to featuresdata_feature, data_feature_outputs = add_gen_flag( data_feature, data_gen_flag, data_feature_outputs, sample_len)generator = DoppelGANgerGenerator( feed_back=False, noise=True, feature_outputs=data_feature_outputs, attribute_outputs=data_attribute_outputs, real_attribute_mask=real_attribute_mask, sample_len=sample_len, feature_num_units=100, feature_num_layers=2)discriminator = Discriminator()attr_discriminator = AttrDiscriminator()
我們使用了由兩層100個神經元組成的神經網絡,用於生成器和鑑別器。 所有數據均經過標準化或1熱編碼。 然後,我們使用以下參數訓練模型:
checkpoint_dir = "./results/checkpoint"sample_path = "./results/time"epoch = 100batch_size = 50g_lr = 0.0001d_lr = 0.0001vis_freq = 50vis_num_sample = 5d_rounds = 3g_rounds = 1d_gp_coe = 10.0attr_d_gp_coe = 10.0g_attr_d_coe = 1.0extra_checkpoint_freq = 30num_packing = 1
如果數據很大,則應使用更多的輪次-作者建議使用400個時期,但在我們的實驗中,我們發現如果網絡不退化和模式崩潰,則可以達到1000個輪次。另外,請考慮時期數與批次大小有關–較小的批次需要更多的時期和較低的學習率。
對於那些不熟悉神經網絡的人來說,批處理,隨機和Minibatch梯度下降是機器學習算法的三種主要形式。批量大小控制訓練神經網絡時誤差梯度估計的準確性。用戶應注意學習期間批次大小,速度和穩定性之間的權衡。較大的批次需要較高的學習率,並且網絡將學習得更快,但是它也可能不穩定,這對於GAN來說尤其是因為模式崩潰問題。
根據經驗,生成器和鑑別器的學習率應該很小(在10–3到10–5之間)並且彼此相似。在本例中,我們使用10–4,而不是默認的10–3。
另一個重要參數是生成器和鑑別器上的回合數。 Wasserstein GAN(WGAN)需要兩個組件才能正常工作:梯度裁剪和比生成器高的鑑別器(dround)。通常,對於發生器的每一輪,鑑別器的輪數在3至5之間。在這裡,我們使用dround = 3和g_round = 1。
為了加快訓練速度,我們對生成器使用了周期性的學習率,對鑑別器使用了固定的學習率。
目錄samplepath存儲在不同檢查點收集的一組樣本,這對於驗證目的很有用。 損失函數的可視化可以在您提供的檢查點目錄上使用TensorBoard完成。 您可以使用參數extracheckpoint_freq控制檢查點的頻率。
請注意,這可能會佔用大量磁碟空間。
run_config = tf.ConfigProto()tf.reset_default_graph() # if you are using spyder with tf.Session(config=run_config) as sess: gan = DoppelGANger( sess=sess, checkpoint_dir=checkpoint_dir, sample_dir=sample_dir, time_path=sample_path, epoch=epoch, batch_size=batch_size, data_feature=data_feature, data_attribute=data_attribute, real_attribute_mask=real_attribute_mask, data_gen_flag=data_gen_flag, sample_len=sample_len, data_feature_outputs=data_feature_outputs, data_attribute_outputs=data_attribute_outputs, vis_freq=vis_freq, vis_num_sample=vis_num_sample, generator=generator, discriminator=discriminator, attr_discriminator=attr_discriminator, d_gp_coe=d_gp_coe, attr_d_gp_coe=attr_d_gp_coe, g_attr_d_coe=g_attr_d_coe, d_rounds=d_rounds, g_rounds=g_rounds,g_lr=g_lr,d_lr=d_lr, num_packing=num_packing, extra_checkpoint_freq=extra_checkpoint_freq) gan.build() gan.train()
綜合數據生成
訓練模型後,您可以使用生成器根據噪聲創建綜合數據。 有兩種方法可以做到這一點:
1. 純噪聲無條件生成
1. 屬性的條件生成
在第一種情況下,我們生成屬性和特徵。 在第二種方法中,我們明確指定要使用哪些屬性來條件化要素生成,以便僅生成要素。
以下是從中生成樣本的代碼:
run_config = tf.ConfigProto()total_generate_num_sample = 1000with tf.Session(config=run_config) as sess: gan = DoppelGANger( sess=sess, checkpoint_dir=checkpoint_dir, sample_dir=sample_dir, time_path=time_path, epoch=epoch, batch_size=batch_size, data_feature=data_feature, data_attribute=data_attribute, real_attribute_mask=real_attribute_mask, data_gen_flag=data_gen_flag, sample_len=sample_len, data_feature_outputs=data_feature_outputs, data_attribute_outputs=data_attribute_outputs, vis_freq=vis_freq, vis_num_sample=vis_num_sample, generator=generator, discriminator=discriminator, attr_discriminator=attr_discriminator, d_gp_coe=d_gp_coe, attr_d_gp_coe=attr_d_gp_coe, g_attr_d_coe=g_attr_d_coe, d_rounds=d_rounds, g_rounds=g_rounds, num_packing=num_packing, extra_checkpoint_freq=extra_checkpoint_freq)# build the network gan.build() length = int(data_feature.shape[1] / sample_len) real_attribute_input_noise = gan.gen_attribute_input_noise( total_generate_num_sample) addi_attribute_input_noise = gan.gen_attribute_input_noise( total_generate_num_sample) feature_input_noise = gan.gen_feature_input_noise( total_generate_num_sample, length) input_data = gan.gen_feature_input_data_free( total_generate_num_sample)# load the weights / change the path accordingly gan.load(checkpoint_dir+'/epoch_id-100')# generate features, attributes and lengths features, attributes, gen_flags, lengths = gan.sample_from( real_attribute_input_noise, addi_attribute_input_noise, feature_input_noise, input_data, given_attribute=None, return_gen_flag_feature=False)#denormalise accordingly features, attributes = renormalize_per_sample( features, attributes, data_feature_outputs, data_attribute_outputs, gen_flags, num_real_attribute=1)
我們需要一些額外的步驟來將生成的樣本處理為序列格式,並以1-hot編碼格式返回向量。
nfloat = len(continuous)synth=np.zeros(features.shape[-1])for i in range(features.shape[0]): v = np.concatenate([np.zeros_like(attributes[i]), np.zeros_like(features[i])],axis=-1) v[attributes[i].shape] = attributes[i] V[attributes[i].shape[0]:attributes[i].shape[0]+1] = feature[i,:,0] for j, c in enumerate(categories_cum[:-1]): ac = features[:,nfloat+categories_cum[j]-1: nfloat+categories_cum[j+1]-1] a_hot = np.zeros((ac.shape[0], categories_n[j])) a_hot[np.arange(ac.shape[0]),ac.argmax(axis=1)] = 1 v[:,nfloat+categories_cum[j]:nfloat+categories_cum[j+1]]=a_hot v=np.concatenate([np.array([i]*len(ac))[np.newaxis].T,v],axis=1) synth = np.vstack([synth,v]) df = pd.DataFrame(synth[1:,1:],columns=processed_df.columns)formated_df = processor.format_df(df)formated_df['account_id']=synth[:,0] # add account_id
下面我們介紹了合成(生成)數據和真實數據之間的一些比較。 我們可以觀察到,總的來說,生成的數據分布與真實數據分布相對匹配-圖8和圖9。
圖8:生成的數據與實際數據之間交易(中間)和標誌(底部)之間的序列長度(頂部)時間間隔的直方圖。
唯一的例外是變量Amount的分布,如圖9所示。這是由於該變量具有不平滑的分布這一事實。 為了解決這個問題,我們將其離散化為20個級別,從而實現了更好的匹配。
圖9:使用連續編碼(頂部)和二值一次熱編碼(底部)生成的實數與實數。
然後,我們使用模糊指標來計算相似度得分。 該分數是三個分數的平均值:直方圖和直方圖2D相似度(實際數據和合成數據直方圖重疊的程度)以及列之間的互信息。 該分數確定了綜合數據保留列之間相關性的程度。
將Amount視為連續變量時,我們獲得的相似度得分為0.57,將其二進位化為20個倉位時,獲得的相似度得分為0.63。 相似度得分如下:
from hazy_trainer.evaluation.similarity import Similaritysim = Similarity(metrics=['hist','hist2d','mi'])score = sim.score(real_df[cols], formated_df[cols])print(score['similarity']['score'])
但是,我們注意到,這個數字並不能真正說明整個故事,因為它沒有明確衡量合成數據序列的時間一致性,而是獨立對待每一行。
圖10:模型隨時間產生的交易金額(入金和出金)。
為此,我們使用了另一個關鍵指標:自相關,它測量時間t中的事件與時間t — ∆發生的事件之間的關係,其中∆是時間滯後。 為了測量關係,我們通過以下方式進行比較:
AC = i = 1T(Areali -Asynthetici)2 / i = 1T(Areali)2
以下是在實際數據和綜合數據上花費的總金額(按天匯總)的自相關圖。 我們可以看到兩者具有非常相似的模式。
這僅適用於數值數據。 對於分類,我們可以使用相互信息。 對於我們的數據,我們得到AC = 0.71
圖11:銀行交易數據集的真實數據和綜合數據的自相關。
為了證明順序數據生成器的功能,我們在另一個更具挑戰性的數據集上進行了測試:Metro Interstate Traffic Volume Data Set。 這是一個包含2012年至2018年每小時流量數據的數據集。正如我們在下圖中看到的那樣,該數據隨著時間的推移相對一致,具有某些每日和每周的模式以及較大的每小時變化性。 來自生成器的綜合數據必須重現所有這些趨勢。
圖12:交通量(每小時車輛)的直方圖。
下圖包含第一個月(2012年10月)的流量,其每日模式可能非常複雜:
圖14:2012年10月的每小時流量模式。每次下降都代表一天。 周末在低流量模式中可見。
為了生成高質量的合成數據,網絡必須預測正確的每日,每周,每月甚至每年的模式,因此長期相關性很重要。
圖15:更多數據分布
在自相關方面,我們可以看到平滑的每日相關性-這很有意義,因為大多數流量具有對稱行為。 早晨的高強度與晚上的高強度相關。
圖15:實際流量數據與生成的流量數據的自相關。 對於更長的分支,合成數據的自相關開始偏離從真實數據獲得的相關性
運行模型
在這種情況下,序列長度是固定的。 為了準備數據,我們使用每月和每周數據的滑動窗口生成了50,000個序列。 該數據集比以前的數據集要大得多,我們希望模型能夠平穩運行而不會崩潰。
在這種情況下,我們還有更多的屬性。 有些是根據數據構建的,例如"星期幾"和"月份":
· 溫度
· 雨
· 雪
· 雲
· 其他天氣情況
· 節日
· 一周中的week
· 月
作為功能,我們只有每小時的流量。 由於我們要捕獲具有最高粒度的變量,因此將所有數值離散化為20個bin,但將流量離散化為50個bin。 該模型運行了200個輪次,批次大小為20,學習率與以前相同。
圖17包含一個真實的和生成的樣本。 我們可以看到,循環模式保持得很好,數據看起來很真實。
圖17:500小時內的真實(頂部)和生成(底部)序列。 該模型是無條件運行的。 我們可以看到,綜合數據很好地捕獲了每日和每周的模式。
為了測試所生成數據的質量,我們提供一些指標—參見表2:
· 相似度-通過直方圖和相互信息的重疊來衡量
· 自相關-超過30個時滯的實數與合成數之比
· 效果—用實數和合成數據訓練時,通過預測誤差的相對比率來衡量
我們使用帶有自舉的LSTM(長期短期記憶)模型作為基準。 該LSTM模型由兩層組成,每層包含100個神經元,並使用30小時的滑動窗口。 這些屬性是通過密集層添加的,並連接到網絡的最後一個隱藏層。
從表2中可以看出,經過每周數據訓練的DoppelGANger的性能相對較好,在引導技術方面表現出色。
表2:流量數據集的結果
我們添加了第三個指標,即順序相互信息(SMI)。 它正在評估包含T列的矩陣上的互信息,其中每列對應於之前的t,t-1,t-2,…t-T時間步長發生的事件,並平均屬性子集。
我們應該注意,該模型可以以屬性為條件,因此我們可以針對特定的天氣條件或一周中的某天或某個月的某天生成樣本。
在最初的工作中,作者通過眾所周知的向鑑別器添加噪聲並削減其梯度的技術(DPGAN)在模型中引入了差異隱私。
但是,他們發現,一旦隱私預算ε變得相對較小(意味著合成數據變得更安全,它也會開始失去質量)(通過相對於真實數據的時間一致性來衡量)。如果數據的最終用途是提取詳細的時間信息,例如事件之間的因果關係,則這可能是一個主要問題。
基於有關PPGAN(隱私保護的生成對抗網絡)的最新工作,我們對注入到鑑別器梯度的噪聲進行了一些修改。瞬間的會計將隱私丟失問題視為一個隨機變量,使用其瞬間生成函數來控制變量的密度分布。此屬性使PPGAN模型訓練更加穩定。當生成非常長的序列時,與DPGAN的區別特別明顯。
噪聲由以下表達式給出:
ɸ= f + N(0,σ2f2)
其中是兩個相鄰點x和x'對查詢f的敏感度:
△f = maxf(x)-f(x')2
該表達式表示,大多數信息點(最高靈敏度)將獲得更多的噪聲添加到漸變,因此不會影響其他點的質量。通過使用經過精心設計的噪聲,我們能夠在交通數據上保留88%的自相關,直到ε= 1。
合成順序數據生成是一個尚未完全解決的難題。 通過上面介紹的測試,我們證明了GAN是解決此問題的有效方法。
本文原始碼:github/fjxmlzn/DoppelGANger
作者:Armando Vieira
deephub翻譯組