aws / aws/sagemaker-huggingface-inference-toolkit
Using Huggingface Estimator - exec: "serve": executable file not found in $PATH
- Dominant language
- Python
- Stars
- 270
- Forks
- 60
- PR merge metrics
- No merged PRs in 30d
Description
I've successfully used the Sagemaker (2.69.0), Huggingface (4.10) and Tensorflow (2.5) libraries to complete training a model, initiated as follows:
```
model_name = 'bert-base-cased'
import datetime
ct = datetime.datetime.now()
current_time = str(ct.now()).replace(":", "-").replace(" ", "-")[:19]
training_job_name=f'finetune-{model_name}-{current_time}'
print( training_job_name )
from sagemaker.huggingface import HuggingFace
# hyperparameters, which are passed into the training job
hyperparameters={'epochs': 1,
'train_batch_size': 16,
'eval_batch_size' : 32,
'model_name': model_name
}
huggingface_estimator = HuggingFace(entry_point='train.py',
source_dir='./scripts',
instance_type='ml.p3.2xlarge',
instance_count=1,
role=role,
transformers_version='4.10',
tensorflow_version='2.5',
py_version='py37',
hyperparameters = hyperparameters)
# starting the train job with our uploaded datasets as input
huggingface_estimator.fit({'train': training_input_path, 'test': test_input_path}, job_name=training_job_name)
```
The training script starts with the usual argument parsing and log configuration. It differs from the samples as it adds some additional layers to the model for fine tuning. It also freezes all the layers in the base bert-base-cased model (to avoid OOM issues, with GPU memory, when training)
```
base_model = TFAutoModel.from_pretrained(args.model_name)
tokenizer = AutoTokenizer.from_pretrained(args.model_name)
# lock base model layers so only the additional task specific layers are
# changed. Trying to get past OOM blocker
for layer in base_model.layers:
layer.trainable=False
# two input layers, we ensure layer name variables match to dictionary keys in TF dataset
input_ids = tf.keras.layers.Input(shape=(512,), name='input_ids', dtype='int32')
mask = tf.keras.layers.Input(shape=(512,), name='attention_mask', dtype='int32')
# we access the transformer model within our bert object using the bert attribute (eg bert.bert instead of bert)
embeddings = base_model.bert(input_ids, attention_mask=mask)[1] # access final activations (alread max-pooled) [1]
# convert bert embeddings into 5 output classes
x = tf.keras.layers.Dense(1024, activation='relu')(embeddings)
y = tf.keras.layers.Dense(5, activation='softmax', name='outputs')(x)
model = tf.keras.Model(inputs=[input_ids, mask], outputs=y)
# fine optimizer and loss
optimizer = tf.keras.optimizers.Adam(learning_rate=args.learning_rate)
loss = tf.keras.losses.CategoricalCrossentropy()
acc = tf.keras.metrics.CategoricalAccuracy('accuracy')
model.compile(optimizer=optimizer, loss=loss, metrics=[acc])
# Preprocess train dataset
train_features = {
"input_ids": train_dataset["input_ids"],
"attention_mask": train_dataset["attention_mask"]
}
tf_train_dataset = tf.data.Dataset.from_tensor_slices((train_features, train_dataset["labels"])).batch(
args.train_batch_size
)
# Preprocess test dataset
test_features = {
"input_ids": test_dataset["input_ids"],
"attention_mask": test_dataset["attention_mask"]
}
tf_test_dataset = tf.data.Dataset.from_tensor_slices((test_features, test_dataset["labels"])).batch(
args.eval_batch_size
)
# Training
if args.do_train:
train_results = model.fit(tf_train_dataset, epochs=args.epochs, batch_size=args.train_batch_size)
logger.info("*** Train ***")
output_eval_file = os.path.join(args.output_data_dir, "train_results.txt")
with open(output_eval_file, "w") as writer:
logger.info("***** Train results *****")
logger.info(train_results)
for key, value in train_results.history.items():
logger.info(" %s = %s", key, value)
writer.write("%s = %s\n" % (key, value))
# Evaluation
if args.do_eval:
result = model.evaluate(tf_test_dataset, batch_size=args.eval_batch_size, return_dict=True)
logger.info("*** Evaluate ***")
output_eval_file = os.path.join(args.output_data_dir, "eval_results.txt")
with open(output_eval_file, "w") as writer:
logger.info("***** Eval results *****")
logger.info(result)
for key, value in result.items():
logger.info(" %s = %s", key, value)
writer.write("%s = %s\n" % (key, value))
# Save result
model_dir = f'{args.model_dir}/00000001'
model.save(model_dir)
tokenizer.save_pretrained(model_dir)
```
I can successfully download the trained model from S3, unzip it in terminal on the SM notebook instance and then load the model directly with Tensorflow to perform inference operations.
```
import tensorflow as tf
model = tf.keras.models.load_model("/home/ec2-user/SageMaker/00000001")
```
So the model seems to have trained correctly and works. However, when I try and deploy as an SM endpoint:
```
from sagemaker.estimator import Estimator
# job which is going to be attached to the estimator
old_training_job_name='finetune-bert-base-cased-2021-12-08-20-18-18'
# attach old training job
huggingface_estimator_loaded = Estimator.attach(old_training_job_name)
# get model output s3 from training job
huggingface_estimator_loaded.model_data
```
This works and displays the expected display for the model_data, but then:
```
predictor = huggingface_estimator_loaded.deploy(1,"ml.g4dn.xlarge")
```
Eventually fails. The Endpoint view in AWS console says: "The primary container for production variant AllTraffic did not pass the ping health check. Please check CloudWatch logs for this endpoint."
Looking into the logs for the endpoint, I see the message repeated 100 times or so:
"exec: "serve": executable file not found in $PATH"
Is this a bug in the Huggingface Docker image, as the only help I've seen for this type of error relates to people hand rolling their containers incorrectly. Or is there some issue in the way that I'm training and saving the model that causes this issue? I've been able to successfully deploy an endpoint with huggingface using the standard samples, so I wonder if this issue is to do with the extra layers that I added to the model? If that's the case I'd love to know how to fix this and this issue would then be a request for more useful logs or errors messages to debug these scenarios.
Thanks!
Contributor guide
Research direction
Start with the SageMaker endpoint CloudWatch logs showing repeated `exec: "serve": executable file not found in $PATH`, then compare this deployment with the working Hugging Face samples. The payload names no repository files or tests, so the first task is to determine whether the failure comes from the custom TensorFlow model artifact or the inference image; done means the cause and a reproducible fix or more useful diagnostic are identified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, huggingface, python, tensorflow
- Domain
- cloud, machine-learning
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100