Генератор ГАН, производящий различимую мощность - PullRequest
1 голос
/ 31 января 2020

Я пытаюсь обучить специальный тип GAN, называемый GAN с поддержкой моделей (https://arxiv.org/pdf/1812.00879), с использованием Keras, который принимает в качестве входного вектора вектор из 13 входных параметров + гауссов шум и генерирует вектор 6 выходов. Отображение между векторами входов и выходов является нетривиальным, так как оно связано с моделированием физики высоких энергий (в частности, моделирование имеет некоторую присущую случайность). Наибольшая зависимость от конечных выходов кодируется в первых пяти входах. Самым большим отличием этой модели от традиционной GAN является использование сиамской сети в качестве дискриминатора, и для этого требуется два входа одновременно, поэтому для одних и тех же входных параметров мы предоставляем два набора возможных выходов для обучения (возможно из-за случайность симуляции), то есть существует 12 выходных распределений, но только 6 являются уникальными, что мы и стремимся сгенерировать. Мы использовали одномерную сверточную нейронную сеть как для дискриминатора, так и для генератора.

Текущая модель, которую мы обучили, похоже, воспроизводит выходные распределения для независимой тестовой выборки с достаточно хорошей точностью (см. График с наложенными гистограммами ниже), но все еще существуют некоторые четкие различия между распределениями и возможной цель состоит в том, чтобы модель могла генерировать неразличимые данные для моделирования. До сих пор я пытался варьировать скорость обучения и добавлял различные степени затухания скорости обучения, настраивая сетевые архитектуры, изменяя некоторые гиперпараметры оптимизатора, добавляя больше шума к обучению дискриминатора, реализуя некоторое сглаживание меток и меняя порядок входов, добавляя некоторое сглаживание меток к обучению генератора, увеличивая размер пакета, а также увеличивая количество шумовых входов, и я до сих пор не могу заставить модель идеально воспроизводить выходные распределения. Я изо всех сил пытаюсь придумать, что делать дальше, и мне было интересно, если у кого-то еще была подобная проблема, из-за которой результат был не совсем идеальным, и если да, то как они могли бы решить эту проблему? Буду признателен за любые мысли или советы!

Я включил полный код для обучения, а также некоторые графики распределения входных и выходных данных (до применения Quantile Transformer), графики потерь для соперника. сеть и дискриминатор (A для Adversarial, S для сиамского (дискриминатор)), а затем наложение гистограмм для сгенерированного и истинного выходных распределений для независимой выборки тестирования (именно здесь вы можете увидеть небольшие различия, которые возникают).

Заранее спасибо.

КОД ОБУЧЕНИЯ

"""
Training implementation
"""

net_range = [-1,1]
gauss_range = [-5.5,5.5]

mapping = interp1d(gauss_range, net_range)

class ModelAssistedGANPID(object):

    def __init__(self, params=64, observables=6):
        self.params = params
        self.observables = observables
        self.Networks = Networks(params=params, observables=observables)
        self.siamese = self.Networks.siamese_model()
        self.adversarial1 = self.Networks.adversarial1_model()

    def train(self, pretrain_steps=4500, train_steps=100000, batch_size=32, train_no=1):

        print('Pretraining for ', pretrain_steps,' steps before training for ', train_steps, ' steps')
        print('Batch size = ', batch_size)
        print('Training number = ', train_no)

        '''
        Pre-training stage
        '''
        # Number of tracks for the training + validation sample
        n_events = 1728000 + 100000
        n_train = n_events - 100000

        # Parameters for Gaussian noise
        lower = -1
        upper = 1
        mu = 0
        sigma = 1

        # import simulation data

        print('Loading data...')

        kaon_data = pd.read_hdf('PATH')

        kaon_data = kaon_data.sample(n=n_events)
        kaon_data = kaon_data.reset_index(drop=True)

        kaon_data_train = kaon_data[:n_train]
        kaon_data_test = kaon_data[n_train:n_events]

        print("Producing training data...")

        # add all inputs

        P_kaon_data_train = kaon_data_train['TrackP']
        Pt_kaon_data_train = kaon_data_train['TrackPt']
        nTracks_kaon_data_train = kaon_data_train['NumLongTracks']
        numRich1_kaon_data_train = kaon_data_train['NumRich1Hits']
        numRich2_kaon_data_train = kaon_data_train['NumRich2Hits']
        rich1EntryX_kaon_data_train = kaon_data_train['TrackRich1EntryX']
        rich1EntryY_kaon_data_train = kaon_data_train['TrackRich1EntryY']
        rich1ExitX_kaon_data_train = kaon_data_train['TrackRich1ExitX']
        rich1ExitY_kaon_data_train = kaon_data_train['TrackRich1ExitY']
        rich2EntryX_kaon_data_train = kaon_data_train['TrackRich2EntryX']
        rich2EntryY_kaon_data_train = kaon_data_train['TrackRich2EntryY']
        rich2ExitX_kaon_data_train = kaon_data_train['TrackRich2ExitX']
        rich2ExitY_kaon_data_train = kaon_data_train['TrackRich2ExitY']

        # add different DLL outputs

        Dlle_kaon_data_train = kaon_data_train['RichDLLe']
        Dlle2_kaon_data_train = kaon_data_train['RichDLLe2']
        Dllmu_kaon_data_train = kaon_data_train['RichDLLmu']
        Dllmu2_kaon_data_train = kaon_data_train['RichDLLmu2']
        Dllk_kaon_data_train = kaon_data_train['RichDLLk']
        Dllk2_kaon_data_train = kaon_data_train['RichDLLk2']
        Dllp_kaon_data_train = kaon_data_train['RichDLLp']
        Dllp2_kaon_data_train = kaon_data_train['RichDLLp2']
        Dlld_kaon_data_train = kaon_data_train['RichDLLd']
        Dlld2_kaon_data_train = kaon_data_train['RichDLLd2']
        Dllbt_kaon_data_train = kaon_data_train['RichDLLbt']
        Dllbt2_kaon_data_train = kaon_data_train['RichDLLbt2']

        # convert to numpy array

        P_kaon_data_train = P_kaon_data_train.to_numpy()
        Pt_kaon_data_train = Pt_kaon_data_train.to_numpy()
        nTracks_kaon_data_train = nTracks_kaon_data_train.to_numpy()
        numRich1_kaon_data_train = numRich1_kaon_data_train.to_numpy()
        numRich2_kaon_data_train = numRich2_kaon_data_train.to_numpy()
        rich1EntryX_kaon_data_train = rich1EntryX_kaon_data_train.to_numpy()
        rich1EntryY_kaon_data_train = rich1EntryY_kaon_data_train.to_numpy()
        rich1ExitX_kaon_data_train = rich1ExitX_kaon_data_train.to_numpy()
        rich1ExitY_kaon_data_train = rich1ExitY_kaon_data_train.to_numpy()
        rich2EntryX_kaon_data_train = rich2EntryX_kaon_data_train.to_numpy()
        rich2EntryY_kaon_data_train = rich2EntryY_kaon_data_train.to_numpy()
        rich2ExitX_kaon_data_train = rich2ExitX_kaon_data_train.to_numpy()
        rich2ExitY_kaon_data_train = rich2ExitY_kaon_data_train.to_numpy()

        Dlle_kaon_data_train = Dlle_kaon_data_train.to_numpy()
        Dlle2_kaon_data_train = Dlle2_kaon_data_train.to_numpy()
        Dllmu_kaon_data_train = Dllmu_kaon_data_train.to_numpy()
        Dllmu2_kaon_data_train = Dllmu2_kaon_data_train.to_numpy()
        Dllk_kaon_data_train = Dllk_kaon_data_train.to_numpy()
        Dllk2_kaon_data_train = Dllk2_kaon_data_train.to_numpy()
        Dllp_kaon_data_train = Dllp_kaon_data_train.to_numpy()
        Dllp2_kaon_data_train = Dllp2_kaon_data_train.to_numpy()
        Dlld_kaon_data_train = Dlld_kaon_data_train.to_numpy()
        Dlld2_kaon_data_train = Dlld2_kaon_data_train.to_numpy()
        Dllbt_kaon_data_train = Dllbt_kaon_data_train.to_numpy()
        Dllbt2_kaon_data_train = Dllbt2_kaon_data_train.to_numpy()

        # Reshape arrays

        P_kaon_data_train = np.array(P_kaon_data_train).reshape(-1, 1)
        Pt_kaon_data_train = np.array(Pt_kaon_data_train).reshape(-1, 1)
        nTracks_kaon_data_train = np.array(nTracks_kaon_data_train).reshape(-1, 1)
        numRich1_kaon_data_train = np.array(numRich1_kaon_data_train).reshape(-1, 1)
        numRich2_kaon_data_train = np.array(numRich2_kaon_data_train).reshape(-1, 1)
        rich1EntryX_kaon_data_train = np.array(rich1EntryX_kaon_data_train).reshape(-1, 1)
        rich1EntryY_kaon_data_train = np.array(rich1EntryY_kaon_data_train).reshape(-1, 1)
        rich1ExitX_kaon_data_train = np.array(rich1ExitX_kaon_data_train).reshape(-1, 1)
        rich1ExitY_kaon_data_train = np.array(rich1ExitY_kaon_data_train).reshape(-1, 1)
        rich2EntryX_kaon_data_train = np.array(rich2EntryX_kaon_data_train).reshape(-1, 1)
        rich2EntryY_kaon_data_train = np.array(rich2EntryY_kaon_data_train).reshape(-1, 1)
        rich2ExitX_kaon_data_train = np.array(rich2ExitX_kaon_data_train).reshape(-1, 1)
        rich2ExitY_kaon_data_train = np.array(rich2ExitY_kaon_data_train).reshape(-1, 1)

        Dlle_kaon_data_train = np.array(Dlle_kaon_data_train).reshape(-1, 1)
        Dlle2_kaon_data_train = np.array(Dlle2_kaon_data_train).reshape(-1, 1)
        Dllmu_kaon_data_train = np.array(Dllmu_kaon_data_train).reshape(-1, 1)
        Dllmu2_kaon_data_train = np.array(Dllmu2_kaon_data_train).reshape(-1, 1)
        Dllk_kaon_data_train = np.array(Dllk_kaon_data_train).reshape(-1, 1)
        Dllk2_kaon_data_train = np.array(Dllk2_kaon_data_train).reshape(-1, 1)
        Dllp_kaon_data_train = np.array(Dllp_kaon_data_train).reshape(-1, 1)
        Dllp2_kaon_data_train = np.array(Dllp2_kaon_data_train).reshape(-1, 1)
        Dlld_kaon_data_train = np.array(Dlld_kaon_data_train).reshape(-1, 1)
        Dlld2_kaon_data_train = np.array(Dlld2_kaon_data_train).reshape(-1, 1)
        Dllbt_kaon_data_train = np.array(Dllbt_kaon_data_train).reshape(-1, 1)
        Dllbt2_kaon_data_train = np.array(Dllbt2_kaon_data_train).reshape(-1, 1)

        inputs_kaon_data_train = np.concatenate((P_kaon_data_train, Pt_kaon_data_train, nTracks_kaon_data_train, numRich1_kaon_data_train, numRich2_kaon_data_train, rich1EntryX_kaon_data_train, 
        rich1EntryY_kaon_data_train, rich1ExitX_kaon_data_train, rich1ExitY_kaon_data_train, rich2EntryX_kaon_data_train, rich2EntryY_kaon_data_train, rich2ExitX_kaon_data_train, rich2ExitY_kaon_data_train), axis=1)
        Dll_kaon_data_train = np.concatenate((Dlle_kaon_data_train, Dllmu_kaon_data_train, Dllk_kaon_data_train, Dllp_kaon_data_train, Dlld_kaon_data_train, Dllbt_kaon_data_train), axis=1)
        Dll2_kaon_data_train = np.concatenate((Dlle2_kaon_data_train, Dllmu2_kaon_data_train, Dllk2_kaon_data_train, Dllp2_kaon_data_train, Dlld2_kaon_data_train, Dllbt2_kaon_data_train), axis=1)

        print('Transforming inputs and outputs using Quantile Transformer...')

        scaler_inputs = QuantileTransformer(output_distribution='normal', n_quantiles=int(1e5), subsample=int(1e10)).fit(inputs_kaon_data_train)
        scaler_Dll = QuantileTransformer(output_distribution='normal', n_quantiles=int(1e5), subsample=int(1e10)).fit(Dll_kaon_data_train)
        scaler_Dll2 = QuantileTransformer(output_distribution='normal', n_quantiles=int(1e5), subsample=int(1e10)).fit(Dll2_kaon_data_train)

        inputs_kaon_data_train = scaler_inputs.transform(inputs_kaon_data_train)
        Dll_kaon_data_train = scaler_Dll.transform(Dll_kaon_data_train)
        Dll2_kaon_data_train = scaler_Dll2.transform(Dll2_kaon_data_train)

        inputs_kaon_data_train = mapping(inputs_kaon_data_train)
        Dll_kaon_data_train = mapping(Dll_kaon_data_train)
        Dll2_kaon_data_train = mapping(Dll2_kaon_data_train)

        # REPEATING FOR TESTING DATA

        print("Producing testing data...")

        # add all inputs

        P_kaon_data_test = kaon_data_test['TrackP']
        Pt_kaon_data_test = kaon_data_test['TrackPt']
        nTracks_kaon_data_test = kaon_data_test['NumLongTracks']
        numRich1_kaon_data_test = kaon_data_test['NumRich1Hits']
        numRich2_kaon_data_test = kaon_data_test['NumRich2Hits']
        rich1EntryX_kaon_data_test = kaon_data_test['TrackRich1EntryX']
        rich1EntryY_kaon_data_test = kaon_data_test['TrackRich1EntryY']
        rich1ExitX_kaon_data_test = kaon_data_test['TrackRich1ExitX']
        rich1ExitY_kaon_data_test = kaon_data_test['TrackRich1ExitY']
        rich2EntryX_kaon_data_test = kaon_data_test['TrackRich2EntryX']
        rich2EntryY_kaon_data_test = kaon_data_test['TrackRich2EntryY']
        rich2ExitX_kaon_data_test = kaon_data_test['TrackRich2ExitX']
        rich2ExitY_kaon_data_test = kaon_data_test['TrackRich2ExitY']

        # add different DLL outputs

        Dlle_kaon_data_test = kaon_data_test['RichDLLe']
        Dlle2_kaon_data_test = kaon_data_test['RichDLLe2']
        Dllmu_kaon_data_test = kaon_data_test['RichDLLmu']
        Dllmu2_kaon_data_test = kaon_data_test['RichDLLmu2']
        Dllk_kaon_data_test = kaon_data_test['RichDLLk']
        Dllk2_kaon_data_test = kaon_data_test['RichDLLk2']
        Dllp_kaon_data_test = kaon_data_test['RichDLLp']
        Dllp2_kaon_data_test = kaon_data_test['RichDLLp2']
        Dlld_kaon_data_test = kaon_data_test['RichDLLd']
        Dlld2_kaon_data_test = kaon_data_test['RichDLLd2']
        Dllbt_kaon_data_test = kaon_data_test['RichDLLbt']
        Dllbt2_kaon_data_test = kaon_data_test['RichDLLbt2']

        # convert to numpy array

        P_kaon_data_test = P_kaon_data_test.to_numpy()
        Pt_kaon_data_test = Pt_kaon_data_test.to_numpy()
        nTracks_kaon_data_test = nTracks_kaon_data_test.to_numpy()
        numRich1_kaon_data_test = numRich1_kaon_data_test.to_numpy()
        numRich2_kaon_data_test = numRich2_kaon_data_test.to_numpy()
        rich1EntryX_kaon_data_test = rich1EntryX_kaon_data_test.to_numpy()
        rich1EntryY_kaon_data_test = rich1EntryY_kaon_data_test.to_numpy()
        rich1ExitX_kaon_data_test = rich1ExitX_kaon_data_test.to_numpy()
        rich1ExitY_kaon_data_test = rich1ExitY_kaon_data_test.to_numpy()
        rich2EntryX_kaon_data_test = rich2EntryX_kaon_data_test.to_numpy()
        rich2EntryY_kaon_data_test = rich2EntryY_kaon_data_test.to_numpy()
        rich2ExitX_kaon_data_test = rich2ExitX_kaon_data_test.to_numpy()
        rich2ExitY_kaon_data_test = rich2ExitY_kaon_data_test.to_numpy()
        Dlle_kaon_data_test = Dlle_kaon_data_test.to_numpy()
        Dlle2_kaon_data_test = Dlle2_kaon_data_test.to_numpy()
        Dllmu_kaon_data_test = Dllmu_kaon_data_test.to_numpy()
        Dllmu2_kaon_data_test = Dllmu2_kaon_data_test.to_numpy()
        Dllk_kaon_data_test = Dllk_kaon_data_test.to_numpy()
        Dllk2_kaon_data_test = Dllk2_kaon_data_test.to_numpy()
        Dllp_kaon_data_test = Dllp_kaon_data_test.to_numpy()
        Dllp2_kaon_data_test = Dllp2_kaon_data_test.to_numpy()
        Dlld_kaon_data_test = Dlld_kaon_data_test.to_numpy()
        Dlld2_kaon_data_test = Dlld2_kaon_data_test.to_numpy()
        Dllbt_kaon_data_test = Dllbt_kaon_data_test.to_numpy()
        Dllbt2_kaon_data_test = Dllbt2_kaon_data_test.to_numpy()

        P_kaon_data_test = np.array(P_kaon_data_test).reshape(-1, 1)
        Pt_kaon_data_test = np.array(Pt_kaon_data_test).reshape(-1, 1)
        nTracks_kaon_data_test = np.array(nTracks_kaon_data_test).reshape(-1, 1)
        numRich1_kaon_data_test = np.array(numRich1_kaon_data_test).reshape(-1, 1)
        numRich2_kaon_data_test = np.array(numRich2_kaon_data_test).reshape(-1, 1)
        rich1EntryX_kaon_data_test = np.array(rich1EntryX_kaon_data_test).reshape(-1, 1)
        rich1EntryY_kaon_data_test = np.array(rich1EntryY_kaon_data_test).reshape(-1, 1)
        rich1ExitX_kaon_data_test = np.array(rich1ExitX_kaon_data_test).reshape(-1, 1)
        rich1ExitY_kaon_data_test = np.array(rich1ExitY_kaon_data_test).reshape(-1, 1)
        rich2EntryX_kaon_data_test = np.array(rich2EntryX_kaon_data_test).reshape(-1, 1)
        rich2EntryY_kaon_data_test = np.array(rich2EntryY_kaon_data_test).reshape(-1, 1)
        rich2ExitX_kaon_data_test = np.array(rich2ExitX_kaon_data_test).reshape(-1, 1)
        rich2ExitY_kaon_data_test = np.array(rich2ExitY_kaon_data_test).reshape(-1, 1)
        Dlle_kaon_data_test = np.array(Dlle_kaon_data_test).reshape(-1, 1)
        Dlle2_kaon_data_test = np.array(Dlle2_kaon_data_test).reshape(-1, 1)
        Dllmu_kaon_data_test = np.array(Dllmu_kaon_data_test).reshape(-1, 1)
        Dllmu2_kaon_data_test = np.array(Dllmu2_kaon_data_test).reshape(-1, 1)
        Dllk_kaon_data_test = np.array(Dllk_kaon_data_test).reshape(-1, 1)
        Dllk2_kaon_data_test = np.array(Dllk2_kaon_data_test).reshape(-1, 1)
        Dllp_kaon_data_test = np.array(Dllp_kaon_data_test).reshape(-1, 1)
        Dllp2_kaon_data_test = np.array(Dllp2_kaon_data_test).reshape(-1, 1)
        Dlld_kaon_data_test = np.array(Dlld_kaon_data_test).reshape(-1, 1)
        Dlld2_kaon_data_test = np.array(Dlld2_kaon_data_test).reshape(-1, 1)
        Dllbt_kaon_data_test = np.array(Dllbt_kaon_data_test).reshape(-1, 1)
        Dllbt2_kaon_data_test = np.array(Dllbt2_kaon_data_test).reshape(-1, 1)

        inputs_kaon_data_test = np.concatenate((P_kaon_data_test, Pt_kaon_data_test, nTracks_kaon_data_test, numRich1_kaon_data_test, numRich2_kaon_data_test, rich1EntryX_kaon_data_test, rich1EntryY_kaon_data_test, rich1ExitX_kaon_data_test, rich1ExitY_kaon_data_test, rich2EntryX_kaon_data_test, rich2EntryY_kaon_data_test, rich2ExitX_kaon_data_test, rich2ExitY_kaon_data_test), axis=1)
        Dll_kaon_data_test = np.concatenate((Dlle_kaon_data_test, Dllmu_kaon_data_test, Dllk_kaon_data_test, Dllp_kaon_data_test, Dlld_kaon_data_test, Dllbt_kaon_data_test), axis=1)
        Dll2_kaon_data_test = np.concatenate((Dlle2_kaon_data_test, Dllmu2_kaon_data_test, Dllk2_kaon_data_test, Dllp2_kaon_data_test, Dlld2_kaon_data_test, Dllbt2_kaon_data_test), axis=1)

        print('Transforming inputs and outputs using Quantile Transformer...')

        inputs_kaon_data_test = scaler_inputs.transform(inputs_kaon_data_test)
        Dll_kaon_data_test = scaler_Dll.transform(Dll_kaon_data_test)
        Dll2_kaon_data_test = scaler_Dll.transform(Dll2_kaon_data_test)

        inputs_kaon_data_test = mapping(inputs_kaon_data_test)
        Dll_kaon_data_test = mapping(Dll_kaon_data_test)
        Dll2_kaon_data_test = mapping(Dll2_kaon_data_test)

        # Producing testing data
        params_list_test = np.random.normal(loc=mu, scale=sigma, size=[len(kaon_data_test), self.params])
        for e in range(len(kaon_data_test)):
            params_list_test[e][0] = inputs_kaon_data_test[e][0]
            params_list_test[e][1] = inputs_kaon_data_test[e][1]
            params_list_test[e][2] = inputs_kaon_data_test[e][2]
            params_list_test[e][3] = inputs_kaon_data_test[e][3]
            params_list_test[e][4] = inputs_kaon_data_test[e][4]
            params_list_test[e][5] = inputs_kaon_data_test[e][5]
            params_list_test[e][6] = inputs_kaon_data_test[e][6]
            params_list_test[e][7] = inputs_kaon_data_test[e][7]
            params_list_test[e][8] = inputs_kaon_data_test[e][8]
            params_list_test[e][9] = inputs_kaon_data_test[e][9]
            params_list_test[e][10] = inputs_kaon_data_test[e][10]
            params_list_test[e][11] = inputs_kaon_data_test[e][11]
            params_list_test[e][12] = inputs_kaon_data_test[e][12]

        obs_simu_1_test = np.zeros((len(kaon_data_test), self.observables, 1))
        obs_simu_1_test.fill(-1)
        for e in range(len(kaon_data_test)):
            obs_simu_1_test[e][0][0] = Dll_kaon_data_test[e][0]
            obs_simu_1_test[e][1][0] = Dll_kaon_data_test[e][1]
            obs_simu_1_test[e][2][0] = Dll_kaon_data_test[e][2]
            obs_simu_1_test[e][3][0] = Dll_kaon_data_test[e][3]
            obs_simu_1_test[e][4][0] = Dll_kaon_data_test[e][4]
            obs_simu_1_test[e][5][0] = Dll_kaon_data_test[e][5]

        obs_simu_2_test = np.zeros((len(kaon_data_test), self.observables, 1))
        obs_simu_2_test.fill(-1)
        for e in range(len(kaon_data_test)):
            obs_simu_2_test[e][0][0] = Dll2_kaon_data_test[e][0]
            obs_simu_2_test[e][1][0] = Dll2_kaon_data_test[e][1]
            obs_simu_2_test[e][2][0] = Dll2_kaon_data_test[e][2]
            obs_simu_2_test[e][3][0] = Dll2_kaon_data_test[e][3]
            obs_simu_2_test[e][4][0] = Dll2_kaon_data_test[e][4]
            obs_simu_2_test[e][5][0] = Dll2_kaon_data_test[e][5]

        event_no_par = 0
        event_no_obs_1 = 0
        event_no_obs_2 = 0

        d1_hist, d2_hist, d_hist, g_hist, a1_hist, a2_hist = list(), list(), list(), list(), list(), list()

        print('Beginning pre-training...')
        '''
        #Pre-training stage
        '''
        for train_step in range(pretrain_steps):
            log_mesg = '%d' % train_step
            noise_value = 0.3
            params_list = np.random.normal(loc=mu,scale=sigma, size=[batch_size, self.params])
            y_ones = np.ones([batch_size, 1])
            y_zeros = np.zeros([batch_size, 1])

            # add physics parameters + noise to params_list

            for b in range(batch_size):
                params_list[b][0] = inputs_kaon_data_train[event_no_par][0]
                params_list[b][1] = inputs_kaon_data_train[event_no_par][1]
                params_list[b][2] = inputs_kaon_data_train[event_no_par][2]
                params_list[b][3] = inputs_kaon_data_train[event_no_par][3]
                params_list[b][4] = inputs_kaon_data_train[event_no_par][4]
                params_list[b][5] = inputs_kaon_data_train[event_no_par][5]
                params_list[b][6] = inputs_kaon_data_train[event_no_par][6]
                params_list[b][7] = inputs_kaon_data_train[event_no_par][7]
                params_list[b][8] = inputs_kaon_data_train[event_no_par][8]
                params_list[b][9] = inputs_kaon_data_train[event_no_par][9]
                params_list[b][10] = inputs_kaon_data_train[event_no_par][10]
                params_list[b][11] = inputs_kaon_data_train[event_no_par][11]
                params_list[b][12] = inputs_kaon_data_train[event_no_par][12]
                event_no_par += 1

            # Step 1
            # simulated observables (number 1)
            obs_simu_1 = np.zeros((batch_size, self.observables, 1))
            obs_simu_1.fill(-1)
            for b in range(batch_size):
                obs_simu_1[b][0][0] = Dll_kaon_data_train[event_no_obs_1][0]
                obs_simu_1[b][1][0] = Dll_kaon_data_train[event_no_obs_1][1]
                obs_simu_1[b][2][0] = Dll_kaon_data_train[event_no_obs_1][2]
                obs_simu_1[b][3][0] = Dll_kaon_data_train[event_no_obs_1][3]
                obs_simu_1[b][4][0] = Dll_kaon_data_train[event_no_obs_1][4]
                obs_simu_1[b][5][0] = Dll_kaon_data_train[event_no_obs_1][5]
                event_no_obs_1 += 1

            obs_simu_1_copy = np.copy(obs_simu_1)

            # simulated observables (Gaussian smeared - number 2)
            obs_simu_2 = np.zeros((batch_size, self.observables, 1))
            obs_simu_2.fill(-1)
            for b in range(batch_size):
                obs_simu_2[b][0][0] = Dll2_kaon_data_train[event_no_obs_2][0]
                obs_simu_2[b][1][0] = Dll2_kaon_data_train[event_no_obs_2][1]
                obs_simu_2[b][2][0] = Dll2_kaon_data_train[event_no_obs_2][2]
                obs_simu_2[b][3][0] = Dll2_kaon_data_train[event_no_obs_2][3]
                obs_simu_2[b][4][0] = Dll2_kaon_data_train[event_no_obs_2][4]
                obs_simu_2[b][5][0] = Dll2_kaon_data_train[event_no_obs_2][5]
                event_no_obs_2 += 1

            obs_simu_2_copy = np.copy(obs_simu_2)

            # emulated DLL values
            obs_emul = self.emulator.predict(params_list)
            obs_emul_copy = np.copy(obs_emul)

            # decay the learn rate
            if(train_step % 1000 == 0 and train_step>0):
                siamese_lr = K.eval(self.siamese.optimizer.lr)
                K.set_value(self.siamese.optimizer.lr, siamese_lr*0.7)
                print('lr for Siamese network updated from %f to %f' % (siamese_lr, siamese_lr*0.7))
                adversarial1_lr = K.eval(self.adversarial1.optimizer.lr)
                K.set_value(self.adversarial1.optimizer.lr, adversarial1_lr*0.7)
                print('lr for Adversarial1 network updated from %f to %f' % (adversarial1_lr, adversarial1_lr*0.7))

            loss_simu_list = [obs_simu_1_copy, obs_simu_2_copy]
            loss_fake_list = [obs_simu_1_copy, obs_emul_copy]

            input_val = 0
            # swap which inputs to give to Siamese network
            if(np.random.random() < 0.5):
                loss_simu_list[0], loss_simu_list[1] = loss_simu_list[1], loss_simu_list[0]

            if(np.random.random() < 0.5):
                loss_fake_list[0] = obs_simu_2_copy
                input_val = 1

            # noise
            y_ones = np.array([np.random.uniform(0.97, 1.00) for x in range(batch_size)]).reshape([batch_size, 1])
            y_zeros = np.array([np.random.uniform(0.00, 0.03) for x in range(batch_size)]).reshape([batch_size, 1])

            if(input_val == 0):
                if np.random.random() < noise_value:
                    for b in range(batch_size):
                        if np.random.random() < noise_value:
                            obs_simu_1_copy[b], obs_simu_2_copy[b] = obs_simu_2[b], obs_simu_1[b]
                            obs_simu_1_copy[b], obs_emul_copy[b] = obs_emul[b], obs_simu_1[b]

            if(input_val == 1):
                if np.random.random() < noise_value:
                    for b in range(batch_size):
                        if np.random.random() < noise_value:
                            obs_simu_1_copy[b], obs_simu_2_copy[b] = obs_simu_2[b], obs_simu_1[b]
                            obs_simu_2_copy[b], obs_emul_copy[b] = obs_emul[b], obs_simu_2[b]

            # train siamese
            d_loss_simu = self.siamese.train_on_batch(loss_simu_list, y_ones)
            d_loss_fake = self.siamese.train_on_batch(loss_fake_list, y_zeros)
            d_loss = 0.5 * np.add(d_loss_simu, d_loss_fake)
            log_mesg = '%s [S loss: %f]' % (log_mesg, d_loss[0])

            #print(log_mesg)
            #print('--------------------')

            #noise_value*=0.999

            #Step 2

            # train emulator

            a_loss_list = [obs_simu_1, params_list]


            a_loss = self.adversarial1.train_on_batch(a_loss_list, y_ones)
            log_mesg = '%s [E loss: %f]' % (log_mesg, a_loss[0])
            print(log_mesg)
            print('--------------------')

            noise_value*=0.999


if __name__ == '__main__':

    params_physics = 13
    params_noise = 51 #51 looks ok, 61 is probably best, 100 also works
    params = params_physics + params_noise
    observables= 6
    train_no = 1

    magan = ModelAssistedGANPID(params=params, observables=observables)
    magan.train(pretrain_steps=11001, train_steps=10000, batch_size=32, train_no=train_no)


СЕТИ

class Networks(object):
    def __init__(self, noise_size=100, params=64, observables=5):

        self.noise_size = noise_size
        self.params = params
        self.observables = observables

        self.E = None # emulator
        self.S = None # siamese
        self.SM = None # siamese model
        self.AM1 = None # adversarial model 1

'''
    Emulator: generate identical observable parameters to those of the simulator S when both E and S are fed with the same input parameters
    '''
    def emulator(self):
        if self.E:
            return self.E

        # input params
        # the model takes as input an array of shape (*, self.params = 6)
        input_params_shape = (self.params,)
        input_params_layer = Input(shape=input_params_shape, name='input_params')

        # architecture
        self.E = Dense(1024)(input_params_layer)
        self.E = LeakyReLU(0.2)(self.E)

        self.E = Dense(self.observables*128, kernel_initializer=initializers.RandomNormal(stddev=0.02))(self.E)
        self.E = LeakyReLU(0.2)(self.E)
        self.E = Reshape((self.observables, 128))(self.E)
        self.E = UpSampling1D(size=2)(self.E)
        self.E = Conv1D(64, kernel_size=7, padding='valid')(self.E)
        self.E = LeakyReLU(0.2)(self.E)
        self.E = UpSampling1D(size=2)(self.E)
        self.E = Conv1D(1, kernel_size=7, padding='valid', activation='tanh')(self.E)

        # model
        self.E = Model(inputs=input_params_layer, outputs=self.E, name='emulator')

        # print
        print("Emulator")
        self.E.summary()

        return self.E

    '''
    Siamese: determine the similarity between output values produced by the simulator and emulator
    '''
    def siamese(self):
        if self.S:
            return self.S

        # input DLL images
        input_shape = (self.observables, 1)
        input_layer_anchor = Input(shape=input_shape, name='input_layer_anchor')
        input_layer_candid = Input(shape=input_shape, name='input_layer_candidate')
        input_layer = Input(shape=input_shape, name='input_layer')

        # siamese
        cnn = Conv1D(64, kernel_size=8, strides=2, padding='same', 
                     kernel_initializer=initializers.RandomNormal(stddev=0.02))(input_layer)
        cnn = LeakyReLU(0.2)(cnn)
        cnn = Conv1D(128, kernel_size=5, strides=2, padding='same')(cnn)
        cnn = LeakyReLU(0.2)(cnn)
        cnn = Flatten()(cnn)
        cnn = Dense(128, activation='sigmoid')(cnn)
        cnn = Model(inputs=input_layer, outputs=cnn, name='cnn')

        # left and right encodings       
        encoded_l = cnn(input_layer_anchor)
        encoded_r = cnn(input_layer_candid)

        # merge two encoded inputs with the L1 or L2 distance between them
        L1_distance = lambda x: K.abs(x[0]-x[1])
        L2_distance = lambda x: (x[0]-x[1]+K.epsilon())**2/(x[0]+x[1]+K.epsilon())
        both = Lambda(L2_distance)([encoded_l, encoded_r])
        prediction = Dense(1, activation='sigmoid')(both)

        # model
        self.S = Model([input_layer_anchor, input_layer_candid], outputs=prediction, name='siamese')

        # print
        print("Siamese:")
        self.S.summary()
        print("Siamese CNN:")
        cnn.summary()

        return self.S

'''
    Siamese model
    '''
    def siamese_model(self):
        if self.SM:
            return self.SM

        # optimizer
        optimizer = Adam(lr=0.004, beta_1=0.5, beta_2=0.9)

        # input DLL values
        input_shape = (self.observables, 1)
        input_layer_anchor = Input(shape=input_shape, name='input_layer_anchor')
        input_layer_candid = Input(shape=input_shape, name='input_layer_candidate')
        input_layer = [input_layer_anchor, input_layer_candid]

        # discriminator
        siamese_ref = self.siamese()
        siamese_ref.trainable = True
        self.SM = siamese_ref(input_layer)

        # model
        self.SM = Model(inputs=input_layer, outputs=self.SM, name='siamese_model')
        self.SM.compile(loss='binary_crossentropy', optimizer=optimizer, metrics=[metrics.binary_accuracy])

        print("Siamese model")
        self.SM.summary()

        return self.SM


    '''
    Adversarial 1 model (adversarial pre-training phase) - this is where the emulator and siamese network are trained to enable the emulator to generate DLL values for a set of given physics inputs
    '''
    def adversarial1_model(self):
        if self.AM1:
            return self.AM1

        optimizer = Adam(lr=0.0004, beta_1=0.5, beta_2=0.9)

        # input 1: simulated DLL values
        input_obs_shape = (self.observables, 1)
        input_obs_layer = Input(shape=input_obs_shape, name='input_obs')

        # input 2: params
        input_params_shape = (self.params, )
        input_params_layer = Input(shape=input_params_shape, name='input_params')

        # emulator
        emulator_ref = self.emulator()
        emulator_ref.trainable = True
        self.AM1 = emulator_ref(input_params_layer)

        # siamese
        siamese_ref = self.siamese()
        siamese_ref.trainable = False
        self.AM1 = siamese_ref([input_obs_layer, self.AM1])

        # model
        input_layer = [input_obs_layer, input_params_layer]
        self.AM1 = Model(inputs=input_layer, outputs=self.AM1, name='adversarial_1_model')
        self.AM1.compile(loss='binary_crossentropy', optimizer=optimizer, metrics=[metrics.binary_accuracy])

        # print
        print("Adversarial 1 model:")
        self.AM1.summary()

        return self.AM1


ПЛАТА ВХОДОВ Inputs Plot ПЛАТА ВЫХОДОВ Outputs Plot График потери Loss plot Общий выход (оранжевый) и истинный выход (синий) Output Comparison Plot

...