InvalidArgumentError: Cannot convert a Tensor of dtype resource to a NumPy array.
@suprateembanerjee The issue occurs in `self.vectorization.get_config()`. 
It contains a non-serializable element, namely the `standardize` element : `'standardize': <bound method TextVectorizer.standardize of <__main__.TextVectorizer object at 0x7846c98d39d0>>`. 
Try filtering out the non-serializable elements from the config before pickling it, like this:
 `serializable_config = {k: v if not callable(v) else None for k, v in config.items()}`. 
Works on [Colab](https://colab.research.google.com/drive/15ptbQqJfaKMUdQsQlca_rXf9WnzM5IDZ#scrollTo=ctmL4l2dmE-C). Hope this helps! @aditya02shah While this does solve the immediate problem, you are not saving the `standardize` method in the pickle file either. Without this information being saved, when the pickle is reloaded for inference, it does not produce the correct vectorization, leading to gibberish translations.

Edit: The methodology seems sound. The unintended artifacts may have been a result of randomized shuffling of the dataset. Seeding this randomization helped mitigate this issue. @suprateembanerjee Explore saving only the necessary configuration and weights, excluding internal layer states that might not be pickle-friendly. Use `layer.get_config() `and `layer.get_weights()`.
Could you please ensure the custom function is compatible with pickling. If it references external objects or resources, make them picklable as well . Please do consider using a plain Python function or a lambda function within the wrapper class.
In order to expedite the trouble-shooting process, please provide the complete code snippet to reproduce the issue reported here. Thank you!
 @sushreebarsa @aditya02shah Aditya's comment pointed me in the right direction. Here's the working wrapper:

```
@keras.utils.register_keras_serializable(package='custom_layers', name='TextVectorizer')
class TextVectorizer(layers.Layer):
    '''English - Spanish Text Vectorizer'''

    def __init__(self, max_tokens=None, output_mode='int', output_sequence_length=None, standardize='lower_and_strip_punctuation', vocabulary=None, config=None):
        super().__init__()
        if config:
            self.vectorization = layers.TextVectorization.from_config(config)

        else:
            self.max_tokens = max_tokens
            self.output_mode = output_mode
            self.output_sequence_length = output_sequence_length
            self.vocabulary = vocabulary
            if standardize != 'lower_and_strip_punctuation':
                self.vectorization = layers.TextVectorization(max_tokens=self.max_tokens,
                                                            output_mode=self.output_mode,
                                                            output_sequence_length=self.output_sequence_length,
                                                            vocabulary=self.vocabulary,
                                                            standardize=self.standardize)
            else:
                self.vectorization = layers.TextVectorization(max_tokens=self.max_tokens,
                                                            output_mode=self.output_mode,
                                                            output_sequence_length=self.output_sequence_length,
                                                            vocabulary=self.vocabulary)


    def standardize(self, input_string, preserve=['[', ']'], add=['¿']) -> str:
        strip_chars = string.punctuation
        for item in add:
            strip_chars += item
        
        for item in preserve:
            strip_chars = strip_chars.replace(item, '')

        lowercase = tf.strings.lower(input_string)
        output = tf.strings.regex_replace(lowercase, f'[{re.escape(strip_chars)}]', '')

        return output
    
    def __call__(self, *args, **kwargs):
        return self.vectorization.__call__(*args, **kwargs)
    
    def get_config(self):
        return {key: value if not callable(value) else None for key, value in self.vectorization.get_config().items()}
    
    def from_config(config):
        return TextVectorizer(config=config)
    
    def set_weights(self, weights):
        self.vectorization.set_weights(weights)

    def adapt(self, dataset):
        self.vectorization.adapt(dataset)
    
    def get_vocabulary(self):
        return self.vectorization.get_vocabulary()
```

To adapt and save the vectorization, 

```
vocab_size = 15000
sequence_length = 20

source_vectorization = TextVectorizer(max_tokens=vocab_size,
                                      output_mode='int',
                                      output_sequence_length=sequence_length)

target_vectorization = TextVectorizer(max_tokens=vocab_size,
                                      output_mode='int',
                                      output_sequence_length=sequence_length + 1,
                                      standardize='spanish')

train_english_texts = [pair[0] for pair in train_pairs]
train_spanish_texts = [pair[1] for pair in train_pairs]
source_vectorization.adapt(train_english_texts)
target_vectorization.adapt(train_spanish_texts)

pickle.dump({'config': source_vectorization.get_config(),
             'weights': source_vectorization.get_weights()}, open('ckpts/english_vectorization.pkl', 'wb'))

pickle.dump({'config': target_vectorization.get_config(),
             'weights': target_vectorization.get_weights()}, open('ckpts/spanish_vectorization.pkl', 'wb'))
```
...and to load it back,
```
vectorization_data = pickle.load(open('ckpts/english_vectorization.pkl', 'rb'))
source_vectorization = TextVectorizer.from_config(vectorization_data['config'])
source_vectorization.set_weights(vectorization_data['weights'])

vectorization_data = pickle.load(open('ckpts/spanish_vectorization.pkl', 'rb'))
target_vectorization = TextVectorizer.from_config(vectorization_data['config'])
target_vectorization.set_weights(vectorization_data['weights'])
``` Are you satisfied with the resolution of your issue?
<a href="https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform?entry.85265664=Yes&entry.2137816233=https://github.com/tensorflow/tensorflow/issues/62756">Yes</a>
<a href="https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform?entry.85265664=No&entry.2137816233=https://github.com/tensorflow/tensorflow/issues/62756">No</a>

### Issue type

Bug

### Have you reproduced the bug with TensorFlow Nightly?

Yes

### Source

source

### TensorFlow version

2.15

### Custom code

Yes

### OS platform and distribution

MacOS Ventura 13.1

### Mobile device

_No response_

### Python version

3.11

### Bazel version

_No response_

### GCC/compiler version

_No response_

### CUDA/cuDNN version

_No response_

### GPU model and memory

_No response_

### Current behavior?

I am trying to save TextVectorization configurations and weights (adapted from training data) into pickle dumps so that they can be initialized at inference time in the absence of training data. I wrote a wrapper class around keras.Layers.TextVectorization() so that I can have access to a custom standardization function. I expect the pickle dump to successfully get created, but instead, this error pops up when I try to create the dump for the case where I am using the custom standardization function.

### Standalone code to reproduce the issue

```shell
@keras.utils.register_keras_serializable(package='custom_layers', name='TextVectorizer')
class TextVectorizer(layers.Layer):
    '''English - Spanish Text Vectorizer'''

    def __init__(self, max_tokens=None, output_mode='int', output_sequence_length=None, standardize='lower_and_strip_punctuation', vocabulary=None):
        super().__init__()
        self.max_tokens = max_tokens
        self.output_mode = output_mode
        self.output_sequence_length = output_sequence_length
        self.vocabulary = vocabulary
        if standardize != 'lower_and_strip_punctuation':
            self.vectorization = layers.TextVectorization(max_tokens=self.max_tokens,
                                                        output_mode=self.output_mode,
                                                        output_sequence_length=self.output_sequence_length,
                                                        vocabulary=self.vocabulary,
                                                        standardize=self.standardize)
        else:
            self.vectorization = layers.TextVectorization(max_tokens=self.max_tokens,
                                                        output_mode=self.output_mode,
                                                        output_sequence_length=self.output_sequence_length,
                                                        vocabulary=self.vocabulary)


    def standardize(self, input_string, preserve=['[', ']'], add=['¿']) -> str:
        strip_chars = string.punctuation
        for item in add:
            strip_chars += item
        
        for item in preserve:
            strip_chars = strip_chars.replace(item, '')

        lowercase = tf.strings.lower(input_string)
        output = tf.strings.regex_replace(lowercase, f'[{re.escape(strip_chars)}]', '')

        return output
    
    def get_config(self):
        return self.vectorization.get_config()

    
    def adapt(self, dataset):
        self.vectorization.adapt(dataset)
    
    def get_vocabulary(self):
        return self.vectorization.get_vocabulary()

vocab_size = 15000
sequence_length = 20

source_vectorization = TextVectorizer(max_tokens=vocab_size,
                                      output_mode='int',
                                      output_sequence_length=sequence_length)

target_vectorization = TextVectorizer(max_tokens=vocab_size,
                                      output_mode='int',
                                      output_sequence_length=sequence_length + 1,
                                      standardize='spanish')

train_english_texts = [pair[0] for pair in train_pairs]
train_spanish_texts = [pair[1] for pair in train_pairs]
source_vectorization.adapt(train_english_texts)
target_vectorization.adapt(train_spanish_texts)

pickle.dump({'config': target_vectorization.get_config(),
             'weights': target_vectorization.get_weights()}
            , open('ckpts/spanish_vectorization.pkl', 'wb'))
```


### Relevant log output

```shell
InvalidArgumentError                      Traceback (most recent call last)
/Users/suprateembanerjee/Library/Mobile Documents/com~apple~CloudDocs/Python Projects/DL With Python/C11.ipynb Cell 79 line 1
----> 1 pickle.dump({'config': target_vectorization.get_config(),
      2              'weights': target_vectorization.get_weights()}
      3             , open('ckpts/spanish_vectorization.pkl', 'wb'))

File ~/miniforge3/envs/tensorflow/lib/python3.11/site-packages/tensorflow/python/framework/ops.py:314, in _EagerTensorBase.__reduce__(self)
    313 def __reduce__(self):
--> 314   return convert_to_tensor, (self._numpy(),)

File ~/miniforge3/envs/tensorflow/lib/python3.11/site-packages/tensorflow/python/framework/ops.py:362, in _EagerTensorBase._numpy(self)
    360   return self._numpy_internal()
    361 except core._NotOkStatusException as e:  # pylint: disable=protected-access
--> 362   raise core._status_to_exception(e) from None

InvalidArgumentError: Cannot convert a Tensor of dtype resource to a NumPy array.
```
