from __future__ import print_function
import os
os.environ['TF_USE_LEGACY_KERAS'] = '1'
from tensorflow.python.keras.models import Sequential
from tensorflow.python.keras.layers import Dense, Activation
import tensorflow as tf
from tensorflow.python.keras.regularizers import l2
from tensorflow.python.keras import backend as K, Input
from tensorflow.python.keras.optimizer_v2.adam import Adam
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder
from sklearn.metrics import roc_curve, auc
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.python.keras.models import Model
from importance_sampling.training import ConstantTimeImportanceTraining
from example_utils import get_parser


def plot_history(history):
    plt.figure(figsize=(12, 5))

    # 绘制训练集和验证集的准确率
    plt.subplot(121)
    plt.plot(history.history['accuracy'])
    plt.plot(history.history['val_accuracy'])
    plt.title('Model accuracy')
    plt.ylabel('Accuracy')
    plt.xlabel('Epoch')
    plt.legend(['Train', 'Validation'], loc='upper left')

    # 绘制训练集和验证集的损失
    plt.subplot(122)
    plt.plot(history.history['loss'])
    plt.plot(history.history['val_loss'])
    plt.title('Model loss')
    plt.ylabel('Loss')
    plt.xlabel('Epoch')
    plt.legend(['Train', 'Validation'], loc='upper left')

    plt.tight_layout()
    plt.show()


def plot_roc_curve(y_test, y_pred):
    n_classes = y_test.shape[1]
    fpr = dict()
    tpr = dict()
    roc_auc = dict()

    for i in range(n_classes):
        fpr[i], tpr[i], _ = roc_curve(y_test[:, i], y_pred[:, i])
        roc_auc[i] = auc(fpr[i], tpr[i])

    # Compute micro-average ROC curve and ROC area
    fpr["micro"], tpr["micro"], _ = roc_curve(y_test.ravel(), y_pred.ravel())
    roc_auc["micro"] = auc(fpr["micro"], tpr["micro"])

    plt.figure()
    plt.plot(fpr["micro"], tpr["micro"],
             label='micro-average ROC curve (area = {0:0.2f})'
                   ''.format(roc_auc["micro"]))
    for i in range(n_classes):
        plt.plot(fpr[i], tpr[i],
                 label='ROC curve of class {0} (area = {1:0.2f})'
                       ''.format(i, roc_auc[i]))

    plt.plot([0, 1], [0, 1], 'k--')
    plt.xlim([0.0, 1.0])
    plt.ylim([0.0, 1.05])
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
    plt.title('Receiver Operating Characteristic (ROC) Curve')
    plt.legend(loc="lower right")
    plt.show()


def calculate_accuracy_fluctuation(history):
    # 获取每个 epoch 的验证集准确率
    val_accuracies = history.history['val_accuracy']

    # 计算平均准确率
    mean_accuracy = np.mean(val_accuracies)

    # 计算每个 epoch 的准确率波动（与均值的绝对差值）
    fluctuation = np.sum(np.abs(val_accuracies - mean_accuracy))

    return mean_accuracy, fluctuation


if __name__ == "__main__":
    parser = get_parser("Train a model on Iris dataset")
    args = parser.parse_args()

    # 导入数据，分别为输入特征和标签
    iris = datasets.load_iris()
    x_data = iris.data
    y_data = iris.target.reshape(-1, 1)

    # 使用OneHotEncoder进行标签的独热编码
    encoder = OneHotEncoder(sparse_output=False)
    y_data = encoder.fit_transform(y_data)

    # 分割数据集为训练集和测试集
    x_train, x_test, y_train, y_test = train_test_split(x_data, y_data, test_size=0.3, random_state=116)

    # 定义神经网络的超参数
    learning_rate = 0.1
    epochs = 100
    batch_size = 8
    num_classes = 3  # 鸢尾花数据集有3个类别

    model = Sequential()
    model.add(Dense(10, activation='relu', input_shape=(4,), kernel_regularizer=l2(1e-5)))
    model.add(Dense(num_classes, kernel_regularizer=l2(1e-5)))
    model.add(Activation('softmax'))

    # **在包装之前编译模型**
    model.compile(
        optimizer=Adam(learning_rate=learning_rate),
        loss='categorical_crossentropy',
        metrics=['accuracy']
    )

    # 在初始化 ConstantTimeImportanceTraining 之前构建模型
    model.predict(np.zeros((1, 4)))  # 这里用模型的输入形状(1, 4)

    # 使用重要性采样训练或常规训练
    if args.importance_training:
        wrapped = ConstantTimeImportanceTraining(model)
    else:
        wrapped = model

    history = wrapped.fit(x_train, y_train,
                          batch_size=batch_size,
                          epochs=epochs,
                          verbose=1,
                          validation_data=(x_test, y_test))

    score = model.evaluate(x_test, y_test, verbose=0)
    print('Test loss:', score[0])
    print('Test accuracy:', score[1])

    # 计算并输出准确率波动
    mean_accuracy, fluctuation = calculate_accuracy_fluctuation(history)
    print('Mean validation accuracy:', mean_accuracy)
    print('Accuracy fluctuation:', fluctuation)

    # 绘制训练历史
    plot_history(history)

    # 计算预测概率
    y_pred = model.predict(x_test)

    # 绘制ROC曲线
    plot_roc_curve(y_test, y_pred)
class ConstantTimeImportanceTraining(_UnbiasedImportanceTraining):
    """主要目的是通过保持每次迭代的时间常量的同时，提高梯度的质量来加速模型训练。

    Arguments
    ---------
        model: The Keras model to train
        score: {"gnorm", "loss", "full_gnorm"}, the importance metric to use
               for importance sampling
        layer: None or int or Layer, the layer to compute the gnorm with
    """

    def __init__(self, model, backward_time=2.0, score="gnorm", layer=None):
        self._backward_time = backward_time

        super(ConstantTimeImportanceTraining, self).__init__(
            model,
            score,
            layer
        )

    def sampler(self, dataset, batch_size, steps_per_epoch, epochs):
        return ConstantTimeSampler(
            dataset,
            self.reweighting,
            self.model,
            backward_time=self._backward_time
        )
class _BaseImportanceTraining(object):
    def __init__(self, model, score="gnorm", layer=None):
        """Abstract base class for training a model using importance sampling.

        Arguments
        ---------
            model: The Keras model to train
        """
        # Wrap and transform the model so that it outputs the importance scores
        # and can be used in an importance sampling training scheme

        self._check_model(model)
        self.original_model = model
        self.model = OracleWrapper(
            model,
            self.reweighting,
            score=score,
            layer=layer
        )
        self.original_model.optimizer = self.model.optimizer
        signal("is.sample").connect(self._on_sample)
        signal("is.score").connect(self._on_scores)

    def _on_sample(self, event):
        self._latest_sample_event = event

    def _on_scores(self, scores):
        self._latest_scores = scores

    def _check_model(self, model):
        """Check if the model uses Dropout and BatchNorm and warn that it may
        affect the importance calculations."""
        if any(
                isinstance(l, (tf.keras.layers.BatchNormalization, Dropout))
                for l in model.layers
        ):
            sys.stderr.write(("[NOTICE]: You are using BatchNormalization "
                              "and/or Dropout.\nThose layers may affect the "
                              "importance calculations and you are advised "
                              "to exchange them for LayerNormalization or "
                              "BatchNormalization in test mode and L2 "
                              "regularization.\n"))

    @property
    def reweighting(self):
        """The reweighting policy that controls the bias of the estimation when
        using importance sampling."""
        raise NotImplementedError()

    def sampler(self, dataset, batch_size, steps_per_epoch, epochs):
        """Create a new sampler to sample from the given dataset using
        importance sampling."""
        raise NotImplementedError()

    def fit(self, x, y, batch_size=32, epochs=1, verbose=1, callbacks=None,
            validation_split=0.0, validation_data=None, steps_per_epoch=None,
            on_sample=None, on_scores=None):
        """Create an `InMemoryDataset` instance with the given data and train
        the model using importance sampling for a given number of epochs.

        Arguments
        ---------
            x: Numpy array of training data or list of numpy arrays
            y: Numpy array of target data
            batch_size: int, number of samples per gradient update
            epochs: int, number of times to iterate over the entire
                    training set
            verbose: {0, >0}, whether to employ the progress bar Keras
                     callback or not
            callbacks: list of Keras callbacks to be called during training
            validation_split: float in [0, 1), percentage of data to use for
                              evaluation
            validation_data: tuple of numpy arrays, Data to evaluate the
                             trained model on without ever training on them
            steps_per_epoch: int or None, number of gradient updates before
                             considering an epoch has passed
            on_sample: callable that accepts the sampler, idxs, w, scores
            on_scores: callable that accepts the sampler and scores
        Returns
        -------
            A Keras `History` object that contains information collected during
            training.
        """
        # Create two data tuples from the given x, y, validation_*
        if validation_data is not None:
            x_train, y_train = x, y
            x_test, y_test = validation_data

        elif validation_split > 0:
            assert validation_split < 1, "100% of the data used for testing"
            n = int(round(validation_split * len(x)))
            idxs = np.arange(len(x))
            np.random.shuffle(idxs)
            x_train, y_train = x[idxs[n:]], y[idxs[n:]]
            x_test, y_test = x[idxs[:n]], y[idxs[:n]]

        else:
            x_train, y_train = x, y
            x_test, y_test = np.empty(shape=(0, 1)), np.empty(shape=(0, 1))

        # Make the dataset to train on
        dataset = InMemoryDataset(
            x_train,
            y_train,
            x_test,
            y_test,
            categorical=False  # this means use the targets as is
        )

        return self.fit_dataset(
            dataset=dataset,
            batch_size=batch_size,
            epochs=epochs,
            steps_per_epoch=steps_per_epoch,
            verbose=verbose,
            callbacks=callbacks,
            on_sample=on_sample,
            on_scores=on_scores
        )

    def fit_generator(self, train, steps_per_epoch=None, batch_size=32,
                      epochs=1, verbose=1, callbacks=None,
                      validation_data=None, validation_steps=None,
                      on_sample=None, on_scores=None):
        """Create a GeneratorDataset instance and train the model using
        importance sampling for a given number of epochs.

        Arguments
        ---------
            train: A generator or iterable that returns tuples (inputs, targets)
            steps_per_epoch: int, number of gradient updates before considering
                             an epoch has passed
            batch_size: int, the number of samples per gradient update
            epochs: int, multiplied by steps_per_epoch denotes the total number
                    of gradient updates
            verbose: {0, >0}, whether to use the progress bar Keras callback
            validation_data: generator, iterable or tuple (inputs, targets)
            validation_steps: None or int, used only if validation_data is a
                              generator
            on_sample: callable that accepts the sampler, idxs, w, scores
            on_scores: callable that accepts the sampler and scores
        """

        def infinite_iterator(iterable):
            while True:
                yield from iterable

        # 创建验证数据集
        if validation_data is not None:
            if isinstance(validation_data, (tuple, list)):
                test = validation_data
                test_len = None
            elif isinstance(validation_data, Iterable):
                test = infinite_iterator(validation_data)
                try:
                    test_len = len(validation_data) * batch_size
                except TypeError:
                    test_len = validation_steps * batch_size if validation_steps else None
            else:
                test = validation_data
                test_len = validation_steps * batch_size if validation_steps else None
        else:
            test = (np.empty(shape=(0, 1)), np.empty(shape=(0, 1)))
            test_len = None
            logging.info("No validation data provided")

        # 设置训练数据和每个 epoch 的步数
        if isinstance(train, Iterable):
            if steps_per_epoch is None:
                try:
                    steps_per_epoch = len(train)
                except TypeError:
                    raise ValueError("steps_per_epoch must be set when using a generator without a __len__ method")
            train = infinite_iterator(train)
        elif steps_per_epoch is None:
            raise ValueError("steps_per_epoch is not set")

        dataset = GeneratorDataset(train, test, test_len)
        try:
            print("dataset.train_data=", len(dataset.train_data))
        except Exception as e:
            print(f"Exception occurred: {e}")

        return self.fit_dataset(
            dataset=dataset,
            batch_size=batch_size,
            epochs=epochs,
            steps_per_epoch=steps_per_epoch,
            verbose=verbose,
            callbacks=callbacks,
            on_sample=on_sample,
            on_scores=on_scores
        )

    def fit_dataset(self, dataset, steps_per_epoch=None, batch_size=32,
                    epochs=1, verbose=1, callbacks=None, on_sample=None,
                    on_scores=None):
        """Train the model on the given dataset for a given number of epochs.

        Arguments
        ---------
            dataset: Instance of `BaseDataset` that provides the data
                     to train on.
            steps_per_epoch: int or None, number of gradient updates before
                             considering an epoch has passed. If None it is set
                             to be `len(dataset.train_data) / batch_size`.
            batch_size: int, number of samples per gradient update
            epochs: int, number of times to iterate `steps_per_epoch` times
            verbose: {0, >0}, whether to employ the progress bar Keras
                     callback or not
            callbacks: list of Keras callbacks to be called during training
            on_sample: callable that accepts the sampler, idxs, w, scores
            on_scores: callable that accepts the sampler and scores
        """
        try:
            if len(dataset.train_data) < batch_size:
                raise ValueError(("The model cannot be trained with "
                                  "batch_size > training set"))
        except RuntimeError as e:
            assert "no size" in str(e)

        # Set steps_per_epoch properly
        if steps_per_epoch is None:
            steps_per_epoch = len(dataset.train_data) // batch_size

        # Create the callbacks list
        # 这段代码的目的是配置和初始化训练过程中将要使用的一组回调函数（callbacks）。
        # 回调函数是在训练的不同阶段被自动调用的函数，用于执行特定的任务，如记录训练指标、
        # 保存模型、早停（early stopping）等
        self.history = History()
        # History是一个回调（Callback），用于在训练过程中记录各种指标（如损失、准确率等）的值
        callbacks = [BaseLogger()] + (callbacks or []) + [self.history]
        if verbose > 0:
            # 添加 ProgbarLogger 回调。ProgbarLogger 用于在终端输出一个进度条，显示训练过程的进度。
            callbacks += [ProgbarLogger(count_mode="steps")]
        callbacks = CallbackList(callbacks)
        callbacks.set_model(self.original_model)
        callbacks.set_params({
            # 设置训练过程的参数
            "epochs": epochs,  # 总共的训练轮数
            "steps": steps_per_epoch,  # 每个 epoch 的步数
            "verbose": verbose,  # 详细程度
            "do_validation": len(dataset.test_data) > 0,  # 是否进行验证
            "metrics": self.metrics_names + [  # 评估指标
                "val_" + n for n in self.metrics_names
            ]
        })

        # 创建采样器
        sampler = self.sampler(dataset, batch_size, steps_per_epoch, epochs)

        # Start the training loop
        epoch = 0
        self.original_model.stop_training = False
        callbacks.on_train_begin()
        while epoch < epochs:
            # 在每个 epoch 开始时执行一些操作 ，
            # 它会遍历所有在 CallbackList 中注册的回调函数，并调用它们的 on_epoch_begin 方法。
            callbacks.on_epoch_begin(epoch)

            for step in range(steps_per_epoch):
                # epoch中的每一step都需要做如下循环
                batch_logs = {"batch": step, "size": batch_size}  # 存储当前批次（batch）训练过程中的相关信息。
                callbacks.on_batch_begin(step, batch_logs)

                # Importance sampling is done here
                idxs, (x, y), w = sampler.sample(batch_size)  # 返回被采样的样本
                # Train on the sampled data
                loss, metrics, scores = self.model.train_batch(x, y, w)
                # Update the sampler
                sampler.update(idxs, scores)

                values = map(lambda x: x.mean(), [loss] + metrics)
                for l, o in zip(self.metrics_names, values):
                    batch_logs[l] = o
                callbacks.on_batch_end(step, batch_logs)

                if on_scores is not None and hasattr(self, "_latest_scores"):
                    on_scores(
                        sampler,
                        self._latest_scores
                    )

                if on_sample is not None:
                    on_sample(
                        sampler,
                        self._latest_sample_event["idxs"],
                        self._latest_sample_event["w"],
                        self._latest_sample_event["predicted_scores"]
                    )

                if self.original_model.stop_training:
                    break

            # Evaluate now that an epoch passed
            epoch_logs = {}
            if len(dataset.test_data) > 0:
                val = self.model.evaluate(
                    *dataset.test_data[:],
                    batch_size=batch_size
                )
                epoch_logs = {
                    "val_" + l: o
                    for l, o in zip(self.metrics_names, val)
                }
            callbacks.on_epoch_end(epoch, epoch_logs)
            if self.original_model.stop_training:
                break
            epoch += 1
        callbacks.on_train_end()

        return self.history

    @property
    def metrics_names(self):
        def name(x):
            if isinstance(x, str):
                return x
            if hasattr(x, "name"):
                return x.name
            if hasattr(x, "__name__"):
                return x.__name__
            return str(x)

        metrics = self.original_model.metrics or []
        return (
                ["loss"] +
                [name(m) for m in metrics] +
                ["score"]
        )


class _UnbiasedImportanceTraining(_BaseImportanceTraining):
    def __init__(self, model, score="gnorm", layer=None):
        self._reweighting = BiasedReweightingPolicy(1.0)  # no bias

        super(_UnbiasedImportanceTraining, self).__init__(model, score, layer)

    @property
    def reweighting(self):
        return self._reweighting
def _tolist(x, acceptable_iterables=(list, tuple)):
    if not isinstance(x, acceptable_iterables):
        x = [x]
    return x


def _get_scoring_layer(score, y_true, y_pred, loss="categorical_crossentropy",
                       layer=None, model=None):
    """Get a scoring layer that computes the score for each pair of y_true,
    y_pred"""
    assert score in ["loss", "gnorm", "full_gnorm", "acc"]

    if score == "loss":
        return LossLayer(loss)([
            y_true,
            y_pred
        ])
    elif score == "gnorm":
        return GradientNormLayer(
            layer.output,
            loss,
            fast=True
        )([
            y_true,
            y_pred
        ])
    elif score == "full_gnorm":
        return GradientNormLayer(
            model.trainable_weights,
            loss,
            fast=False
        )([
            y_true,
            y_pred
        ])
    elif score == "acc":
        return LossLayer(categorical_accuracy)([
            y_true,
            y_pred
        ])


class ModelWrapper(object):
    """The goal of the ModelWrapper is to take a NN and add some extra layers
    that produce a score, a loss and the sample weights to perform importance
    sampling."""
    def _iterate_batches(self, x, y, batch_size):
        bs = batch_size
        for s in range(0, len(y), bs):
            yield [xi[s:s+bs] for xi in _tolist(x)], y[s:s+bs]

    def evaluate(self, x, y, batch_size=128):
        result = np.mean(
            np.vstack([
                self.evaluate_batch(xi, yi)
                for xi, yi in self._iterate_batches(x, y, batch_size)
            ]),
            axis=0
        )

        signal("is.evaluation").send(result)
        return result

    def score(self, x, y, batch_size=128):
        bs = batch_size
        result = np.hstack([
            self.score_batch(xi, yi).T
            for xi, yi in self._iterate_batches(x, y, batch_size)
        ]).T

        signal("is.score").send(result)
        return result

    def set_lr(self, lr):
        """Set the learning rate of the wrapped models.

        We try to set the learning rate on a member variable model and a member
        variable small. If we do not find a member variable model we raise a
        NotImplementedError
        """
        try:
            K.set_value(
                self.optimizer.lr,
                lr
            )
        except AttributeError:
            try:
                K.set_value(
                    self.model.optimizer.lr,
                    lr
                )
            except AttributeError:
                raise NotImplementedError()

        try:
            K.set_value(
                self.small.optimizer.lr,
                lr
            )
        except AttributeError:
            pass

    def evaluate_batch(self, x, y):
        raise NotImplementedError()

    def score_batch(self, x, y):
        raise NotImplementedError()

    def train_batch(self, x, y, w):
        raise NotImplementedError()
class GradientNormLayer(Layer):
    """GradientNormLayer aims to output the gradient norm given a list of
    parameters (whose gradient to compute) and a loss function to combine the
    two inputs.
    
    # Arguments
        parameter_list: A list of Keras variables to compute the gradient
                        norm for
        loss: The loss function to use to combine the model output and the
              target into a scalar and then compute the gradient norm
        fast: If set to True it means we know that the gradient with respect to
              each sample only affects one part of the parameter list so we can
              use the batch mode to compute the gradient
    """
    def __init__(self, parameter_list, loss, fast=False, **kwargs):
        self.supports_masking = True
        self.parameter_list = parameter_list
        self.loss = losses.get(loss)
        self.fast = fast

        super(GradientNormLayer, self).__init__(**kwargs)

    def compute_mask(self, inputs, input_mask):
        return None

    def build(self, input_shape):
        pass # Nothing to do

        super(GradientNormLayer, self).build(input_shape)

    def compute_output_shape(self, input_shape):
        # We get two inputs
        assert len(input_shape) == 2

        return (input_shape[0][0], 1)

    def call(self, x, mask=None):
        # x should be an output and a target
        assert len(x) == 2

        losses = _per_sample_loss(self.loss, mask, x)
        if self.fast:
            grads = K.sqrt(K.sum([
                self._sum_per_sample(K.square(g))
                for g in K.gradients(losses, self.parameter_list)
            ]))
        else:
            nb_samples = K.shape(losses)[0]
            grads = K.map_fn(
                lambda i: self._grad_norm(losses[i]),
                K.arange(0, nb_samples),
                dtype=K.floatx()
            )

        return K.reshape(grads, (-1, 1))

    def _sum_per_sample(self, x):
        """Sum across all the dimensions except the batch dim"""
        # Instead we might be able to use x.ndims but there have been problems
        # with ndims and Keras so I think len(int_shape()) is more reliable
        dims = len(K.int_shape(x))
        return K.sum(x, axis=list(range(1, dims)))

    def _grad_norm(self, loss):
        grads = K.gradients(loss, self.parameter_list)
        return K.sqrt(
            sum([
                K.sum(K.square(g))
                for g in grads
            ])
        )
上述代码报错Traceback (most recent call last):
  File "C:\代码备份库\importance-sampling-master-yuanweihua-QNN-pennylane\examples\yuanweihua.py", line 132, in <module>
    wrapped = ConstantTimeImportanceTraining(model)
  File "C:\代码备份库\importance-sampling-master-yuanweihua-QNN-pennylane\importance_sampling\training.py", line 466, in __init__
    super(ConstantTimeImportanceTraining, self).__init__(
  File "C:\代码备份库\importance-sampling-master-yuanweihua-QNN-pennylane\importance_sampling\training.py", line 363, in __init__
    super(_UnbiasedImportanceTraining, self).__init__(model, score, layer)
  File "C:\代码备份库\importance-sampling-master-yuanweihua-QNN-pennylane\importance_sampling\training.py", line 40, in __init__
    self.model = OracleWrapper(
  File "C:\代码备份库\importance-sampling-master-yuanweihua-QNN-pennylane\importance_sampling\model_wrappers.py", line 172, in __init__
    self._augment_model(model, score, reweighting)
  File "C:\代码备份库\importance-sampling-master-yuanweihua-QNN-pennylane\importance_sampling\model_wrappers.py", line 226, in _augment_model
    score_tensor = _get_scoring_layer(
  File "C:\代码备份库\importance-sampling-master-yuanweihua-QNN-pennylane\importance_sampling\model_wrappers.py", line 41, in _get_scoring_layer
    return GradientNormLayer(
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\keras\engine\base_layer.py", line 983, in __call__
    return self._functional_construction_call(inputs, args, kwargs,
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\keras\engine\base_layer.py", line 1121, in _functional_construction_call
    outputs = self._keras_tensor_symbolic_call(
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\keras\engine\base_layer.py", line 854, in _keras_tensor_symbolic_call
    return self._infer_output_signature(inputs, args, kwargs, input_masks)
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\keras\engine\base_layer.py", line 894, in _infer_output_signature
    outputs = call_fn(inputs, *args, **kwargs)
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\autograph\impl\api.py", line 692, in wrapper
    raise e.ag_error_metadata.to_exception(e)
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\autograph\impl\api.py", line 689, in wrapper
    return converted_call(f, args, kwargs, options=options)
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\autograph\impl\api.py", line 439, in converted_call
    result = converted_f(*effective_args, **kwargs)
  File "C:\Users\LIUWEN~1\AppData\Local\Temp\__autograph_generated_filek3u6uuvd.py", line 30, in tf__call
    ag__.if_stmt(ag__.ld(self).fast, if_body, else_body, get_state, set_state, ('grads',), 1)
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\autograph\operators\control_flow.py", line 1363, in if_stmt
    _py_if_stmt(cond, body, orelse)
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\autograph\operators\control_flow.py", line 1416, in _py_if_stmt
    return body() if cond else orelse()
  File "C:\Users\LIUWEN~1\AppData\Local\Temp\__autograph_generated_filek3u6uuvd.py", line 22, in if_body
    grads = ag__.converted_call(ag__.ld(K).sqrt, (ag__.converted_call(ag__.ld(K).sum, ([ag__.converted_call(ag__.ld(self)._sum_per_sample, (ag__.converted_call(ag__.ld(K).square, (ag__.ld(g),), None, fscope),), None, fscope) for g in ag__.converted_call(ag__.ld(K).gradients, (ag__.ld(losses), ag__.ld(self).parameter_list), None, fscope)],), None, fscope),), None, fscope)
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\autograph\impl\api.py", line 377, in converted_call
    return _call_unconverted(f, args, kwargs, options)
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\autograph\impl\api.py", line 459, in _call_unconverted
    return f(*args)
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\keras\backend.py", line 4143, in gradients
    return gradients_module.gradients(
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\ops\gradients_impl.py", line 165, in gradients
    return gradients_util._GradientsHelper(
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\ops\gradients_util.py", line 536, in _GradientsHelper
    xs = ops.internal_convert_n_to_tensor_or_indexed_slices(
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\framework\indexed_slices.py", line 366, in internal_convert_n_to_tensor_or_indexed_slices
    internal_convert_to_tensor_or_indexed_slices(
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\framework\indexed_slices.py", line 327, in internal_convert_to_tensor_or_indexed_slices
    return ops.convert_to_tensor(value, dtype=dtype, name=name, as_ref=as_ref)
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\profiler\trace.py", line 183, in wrapped
    return func(*args, **kwargs)
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\framework\ops.py", line 1638, in convert_to_tensor
    ret = conversion_func(value, dtype=dtype, name=name, as_ref=as_ref)
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\framework\constant_op.py", line 343, in _constant_tensor_conversion_function
    return constant(v, dtype=dtype, name=name)
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\framework\constant_op.py", line 267, in constant
    return _constant_impl(value, dtype, shape, name, verify_shape=False,
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\framework\constant_op.py", line 284, in _constant_impl
    tensor_util.make_tensor_proto(
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\framework\tensor_util.py", line 432, in make_tensor_proto
    values = np.asarray(values)
  File "C:\Users\liuwenjing\.conda\envs\pennylane_qiskit\lib\site-packages\tensorflow\python\keras\engine\keras_tensor.py", line 254, in __array__
    raise TypeError(
TypeError: in user code:

    File "C:\代码备份库\importance-sampling-master-yuanweihua-QNN-pennylane\importance_sampling\layers\scores.py", line 119, in call  *
        grads = K.sqrt(K.sum([

    TypeError: Cannot convert a symbolic Keras input/output to a numpy array. This error may indicate that you're trying to pass a symbolic value to a NumPy call, which is not supported. Or, you may be trying to pass Keras symbolic inputs/outputs to a TF API that does not register dispatching, preventing Keras from automatically converting the API call to a lambda layer in the Functional Model.


Process finished with exit code 1
如何进行修改,用中文进行表述