Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Important
L’inscription de fonctions définies par l’utilisateur Python dans le catalogue Unity est disponible en préversion publique.
Une fonction de table définie par l’utilisateur du catalogue Unity enregistre les fonctions qui retournent des tables complètes au lieu de valeurs scalaires. Contrairement aux fonctions scalaires qui retournent une valeur de résultat unique à partir de chaque appel, les fonctions définies par l’utilisateur sont appelées dans la clause d’une FROM instruction SQL et peuvent retourner plusieurs lignes et colonnes.
Les fonctions définies par l’utilisateur sont particulièrement utiles pour :
- Transformation de tableaux ou de structures de données complexes en plusieurs lignes
- Intégration d’API ou de services externes dans des flux de travail SQL
- Implémentation d’une logique d’enrichissement ou de génération de données personnalisée
- Traitement des données nécessitant des opérations avec état sur plusieurs lignes
Chaque appel UDTF accepte zéro ou plusieurs arguments. Ces arguments peuvent être des expressions scalaires ou des arguments de table représentant des tables d’entrée entières.
Les fonctions définies par l’utilisateur peuvent être inscrites de deux manières :
- Catalogue Unity : Inscrivez l’UDTF en tant qu’objet régi dans le catalogue Unity.
- Étendue à la session : Inscrivez-vous au bloc-notes ou au travail local
SparkSessionisolé. Consultez les fonctions de table définies par l’utilisateur Python (UDF) .
Spécifications
Les fonctions définies par l’utilisateur Python du catalogue Unity sont prises en charge sur les types de calcul suivants :
- Calcul classique avec mode d’accès standard (Databricks Runtime 17.1 et versions ultérieures)
- SQL Warehouse (serverless ou pro)
Créer un UDTF dans le catalogue Unity
Utilisez SQL DDL pour créer un UDTF régi dans le catalogue Unity. Les fonctions de table définies par l’utilisateur (UDTFs) sont appelées en utilisant la clause FROM d'une instruction SQL.
CREATE OR REPLACE FUNCTION square_numbers(start INT, end INT)
RETURNS TABLE (num INT, squared INT)
LANGUAGE PYTHON
HANDLER 'SquareNumbers'
DETERMINISTIC
AS $$
class SquareNumbers:
"""
Basic UDTF that computes a sequence of integers
and includes the square of each number in the range.
"""
def eval(self, start: int, end: int):
for num in range(start, end + 1):
yield (num, num * num)
$$;
SELECT * FROM square_numbers(1, 5);
+-----+---------+
| num | squared |
+-----+---------+
| 1 | 1 |
| 2 | 4 |
| 3 | 9 |
| 4 | 16 |
| 5 | 25 |
+-----+---------+
Azure Databricks implémente les UDTF (fonctions de table définies par l'utilisateur) Python sous forme de classes Python avec une méthode obligatoire eval qui génère des lignes de sortie.
Arguments de table
Note
TABLE les arguments sont pris en charge dans Databricks Runtime 17.2 et versions ultérieures.
Les UDTFs peuvent accepter des tables entières comme arguments d’entrée, permettant des transformations complexes et des agrégations avec maintien d'état.
eval() et terminate() méthodes de cycle de vie
Les arguments de table dans les fonctions définies par l’utilisateur utilisent les fonctions suivantes pour traiter chaque ligne :
-
eval(): appelé une seule fois pour chaque ligne de la table d’entrée. Il s’agit de la méthode de traitement principale et est requise. -
terminate(): appelé une fois à la fin de chaque partition, une fois toutes les lignes traitées pareval(). Utilisez cette méthode pour générer des résultats agrégés finaux ou effectuer des opérations de nettoyage. Cette méthode est facultative, mais essentielle pour les opérations avec état telles que les agrégations, le comptage ou le traitement par lots.
Pour plus d’informations sur les méthodes eval() et terminate(), consultez la documentation Apache Spark : Python UDTF.
Modèles d’accès aux lignes
eval() reçoit des lignes d’arguments TABLE en tant qu’objets pyspark.sql.Row . Vous pouvez accéder aux valeurs par nom de colonne (row['id'], row['name']) ou par index (row[0], row[1]).
-
Flexibilité du schéma : déclarez TABLE des arguments sans définitions de schéma (par exemple,
data TABLE,t TABLE). La fonction accepte n’importe quelle structure de table. Votre code doit donc vérifier que les colonnes requises existent.
Voir Exemple : Mettre en correspondance les adresses IP par rapport aux blocs réseau CIDR et Exemple : sous-titrage d’images Batch à l’aide de points de terminaison de vision Azure Databricks.
Isolation de l’environnement
Note
Les environnements d’isolation partagé nécessitent Databricks Runtime 17.2 et versions ultérieures. Dans les versions antérieures, tous les UDF Python du catalogue Unity s’exécutent en mode d’isolation strict.
Les fonctions définies par l’utilisateur python du catalogue Unity avec le même propriétaire et la même session peuvent partager un environnement d’isolation par défaut. Cela améliore les performances et réduit l’utilisation de la mémoire en réduisant le nombre d’environnements distincts qui doivent être lancés.
Isolation stricte
Pour garantir qu’une UDTF s’exécute toujours dans son propre environnement entièrement isolé, ajoutez la STRICT ISOLATION clause caractéristique.
La plupart des fonctions définies par l’utilisateur n’ont pas besoin d’une isolation stricte. Les fonctions définies par l’utilisateur pour le traitement des données standard bénéficient de l’environnement d’isolation partagé par défaut et s’exécutent plus rapidement avec une consommation de mémoire inférieure.
Ajoutez la clause caractéristique aux fonctions définies par l’utilisateur STRICT ISOLATION qui :
- Exécutez l’entrée en tant que code à l’aide de fonctions similaires
eval(), ou à l’aideexec()de fonctions similaires. - Écrivez des fichiers dans le système de fichiers local.
- Modifiez les variables globales ou l’état système.
- Accéder ou modifier des variables d’environnement.
L’exemple UDTF suivant définit une variable d’environnement personnalisée, lit la variable en arrière et multiplie un ensemble de nombres à l’aide de la variable. Étant donné que l’UDTF mute l’environnement de processus, exécutez-le dans STRICT ISOLATION. Sinon, il peut fuiter ou remplacer des variables d’environnement pour d’autres fonctions définies par l’utilisateur/fonctions définies par l’utilisateur dans le même environnement, ce qui provoque un comportement incorrect.
CREATE OR REPLACE TEMPORARY FUNCTION multiply_numbers(factor STRING)
RETURNS TABLE (original INT, scaled INT)
LANGUAGE PYTHON
STRICT ISOLATION
HANDLER 'Multiplier'
AS $$
import os
class Multiplier:
def eval(self, factor: str):
# Save the factor as an environment variable
os.environ["FACTOR"] = factor
# Read it back and convert it to a number
scale = int(os.getenv("FACTOR", "1"))
# Multiply 0 through 4 by the factor
for i in range(5):
yield (i, i * scale)
$$;
SELECT * FROM multiply_numbers("3");
Définir DETERMINISTIC si votre fonction produit des résultats cohérents
Ajoutez DETERMINISTIC à votre définition de fonction s’il produit les mêmes sorties pour les mêmes entrées. Cela permet aux optimisations des requêtes d’améliorer les performances.
Par défaut, les fonctions définies par l'utilisateur Python UDTFs du Batch Unity Catalog sont supposées être non déterministes, sauf déclaration explicite. Parmi les exemples de fonctions non déterministes, citons la génération de valeurs aléatoires, l’accès aux heures ou dates actuelles ou l’exécution d’appels d’API externes.
Consultez CREATE FUNCTION (SQL et Python).
Exemples pratiques
Les exemples suivants illustrent des cas d’usage réels pour les fonctions définies par l’utilisateur Python du catalogue Unity, en passant de transformations de données simples à des intégrations externes complexes.
Exemple : réapplémentation explode
Alors que Spark fournit une fonction intégrée explode , la création de votre propre version illustre le modèle UDTF fondamental de la prise d’une entrée unique et la production de plusieurs lignes de sortie.
CREATE OR REPLACE FUNCTION my_explode(arr ARRAY<STRING>)
RETURNS TABLE (element STRING)
LANGUAGE PYTHON
HANDLER 'MyExplode'
DETERMINISTIC
AS $$
class MyExplode:
def eval(self, arr):
if arr is None:
return
for element in arr:
yield (element,)
$$;
Utilisez la fonction directement dans une requête SQL :
SELECT element FROM my_explode(array('apple', 'banana', 'cherry'));
+---------+
| element |
+---------+
| apple |
| banana |
| cherry |
+---------+
Vous pouvez également l’appliquer aux données de table existantes avec une LATERAL jointure :
SELECT s.*, e.element
FROM my_items AS s,
LATERAL my_explode(s.items) AS e;
Exemple : géolocalisation d’adresses IP via l’API REST
Cet exemple montre comment les fonctions définies par l’utilisateur peuvent intégrer des API externes directement dans votre flux de travail SQL. Les analystes peuvent enrichir des données avec des appels d’API en temps réel à l’aide d’une syntaxe SQL familière, sans nécessiter de processus ETL distincts.
CREATE OR REPLACE FUNCTION ip_to_location(ip_address STRING)
RETURNS TABLE (city STRING, country STRING)
LANGUAGE PYTHON
HANDLER 'IPToLocationAPI'
AS $$
class IPToLocationAPI:
def eval(self, ip_address):
import requests
api_url = f"https://api.ip-lookup.example.com/{ip_address}"
try:
response = requests.get(api_url)
response.raise_for_status()
data = response.json()
yield (data.get('city'), data.get('country'))
except requests.exceptions.RequestException as e:
# Return nothing if the API request fails
return
$$;
Note
Les fonctions définies par l’utilisateur Python autorisent le trafic réseau TCP/UDP sur les ports 80, 443 et 53 lors de l’utilisation du calcul ou du calcul serverless configuré avec le mode d’accès standard.
Utilisez la fonction pour enrichir les données de journal web avec des informations géographiques :
SELECT
l.timestamp,
l.request_path,
geo.city,
geo.country
FROM web_logs AS l,
LATERAL ip_to_location(l.ip_address) AS geo;
Cette approche permet une analyse géographique en temps réel sans nécessiter de tables de recherche prétraitées ou de pipelines de données distincts. L’UDTF gère les requêtes HTTP, l’analyse JSON et la gestion des erreurs, ce qui rend les sources de données externes accessibles via des requêtes SQL standard.
Exemple : Mettre en correspondance les adresses IP par rapport aux blocs réseau CIDR
Cet exemple illustre la correspondance d’adresses IP par rapport aux blocs réseau CIDR, une tâche courante d’ingénierie des données qui nécessite une logique SQL complexe.
Tout d’abord, créez des exemples de données avec des adresses IPv4 et IPv6 :
-- An example IP logs with both IPv4 and IPv6 addresses
CREATE OR REPLACE TEMPORARY VIEW ip_logs AS
VALUES
('log1', '192.168.1.100'),
('log2', '10.0.0.5'),
('log3', '172.16.0.10'),
('log4', '8.8.8.8'),
('log5', '2001:db8::1'),
('log6', '2001:db8:85a3::8a2e:370:7334'),
('log7', 'fe80::1'),
('log8', '::1'),
('log9', '2001:db8:1234:5678::1')
t(log_id, ip_address);
Ensuite, définissez et inscrivez l’UDTF. Notez la structure de classe Python :
- Le
t TABLEparamètre accepte une table d’entrée avec n’importe quel schéma. L’UDTF s’adapte automatiquement pour traiter les colonnes disponibles. Cette flexibilité signifie que vous pouvez utiliser la même fonction entre différentes tables sans modifier la signature de fonction. Toutefois, vous devez vérifier soigneusement le schéma des lignes pour garantir la compatibilité. - La méthode
__init__est utilisée pour une configuration intensive et ponctuelle, comme le chargement de la liste volumineuse de réseaux. Ce travail a lieu une fois pour chaque partition de la table d’entrée. - La
evalméthode traite chaque ligne et contient la logique de correspondance principale. Cette méthode s’exécute exactement une fois pour chaque ligne de la partition d’entrée, et chaque exécution est effectuée par l’instance correspondante de laIpMatcherclasse UDTF pour cette partition. - La
HANDLERclause spécifie le nom de la classe Python qui implémente la logique UDTF.
CREATE OR REPLACE TEMPORARY FUNCTION ip_cidr_matcher(t TABLE)
RETURNS TABLE(log_id STRING, ip_address STRING, network STRING, ip_version INT)
LANGUAGE PYTHON
HANDLER 'IpMatcher'
COMMENT 'Match IP addresses against a list of network CIDR blocks'
AS $$
class IpMatcher:
def __init__(self):
import ipaddress
# Heavy initialization - load networks once per partition
self.nets = []
cidrs = ['192.168.0.0/16', '10.0.0.0/8', '172.16.0.0/12',
'2001:db8::/32', 'fe80::/10', '::1/128']
for cidr in cidrs:
self.nets.append(ipaddress.ip_network(cidr))
def eval(self, row):
import ipaddress
# Validate that required fields exist
required_fields = ['log_id', 'ip_address']
for field in required_fields:
if field not in row:
raise ValueError(f"Missing required field: {field}")
try:
ip = ipaddress.ip_address(row['ip_address'])
for net in self.nets:
if ip in net:
yield (row['log_id'], row['ip_address'], str(net), ip.version)
return
yield (row['log_id'], row['ip_address'], None, ip.version)
except ValueError:
yield (row['log_id'], row['ip_address'], 'Invalid', None)
$$;
Maintenant que ip_cidr_matcher est inscrit dans Unity Catalog, appelez-le directement depuis SQL en utilisant la syntaxe TABLE() :
-- Process all IP addresses
SELECT
*
FROM
ip_cidr_matcher(t => TABLE(ip_logs))
ORDER BY
log_id;
+--------+-------------------------------+-----------------+-------------+
| log_id | ip_address | network | ip_version |
+--------+-------------------------------+-----------------+-------------+
| log1 | 192.168.1.100 | 192.168.0.0/16 | 4 |
| log2 | 10.0.0.5 | 10.0.0.0/8 | 4 |
| log3 | 172.16.0.10 | 172.16.0.0/12 | 4 |
| log4 | 8.8.8.8 | null | 4 |
| log5 | 2001:db8::1 | 2001:db8::/32 | 6 |
| log6 | 2001:db8:85a3::8a2e:370:7334 | 2001:db8::/32 | 6 |
| log7 | fe80::1 | fe80::/10 | 6 |
| log8 | ::1 | ::1/128 | 6 |
| log9 | 2001:db8:1234:5678::1 | 2001:db8::/32 | 6 |
+--------+-------------------------------+-----------------+-------------+
Exemple : sous-titrage d’images par lots à l’aide des points de terminaison Vision d'Azure Databricks
Cet exemple illustre le sous-titrage d’images par lots à l’aide d’un modèle de vision Azure Databricks servant le point de terminaison. Il présente l’utilisation terminate() pour le traitement par lots et l’exécution basée sur la partition.
Créez une table avec des URL d’image publique :
CREATE OR REPLACE TEMPORARY VIEW sample_images AS VALUES ('https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg', 'scenery'), ('https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Camponotus_flavomarginatus_ant.jpg/1024px-Camponotus_flavomarginatus_ant.jpg', 'animals'), ('https://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Cat_August_2010-4.jpg/1200px-Cat_August_2010-4.jpg', 'animals'), ('https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/M101_hires_STScI-PRC2006-10a.jpg/1024px-M101_hires_STScI-PRC2006-10a.jpg', 'scenery') images(image_url, category);Créez un UDTF python du catalogue Unity pour générer des légendes d’image :
- Initialisez l'UDTF avec la configuration, y compris la taille du lot, le jeton d'API Azure Databricks, le point de terminaison du modèle de vision et l'URL de l'espace de travail.
- Dans la
evalméthode, collectez les URL d’image dans une mémoire tampon. Lorsque la mémoire tampon atteint la taille du lot, déclenchez le traitement par lots. Cela garantit que plusieurs images sont traitées ensemble dans un seul appel d’API plutôt que des appels individuels par image. - Dans la méthode de traitement par lots, téléchargez toutes les images mises en mémoire tampon, encodez-les en base64 et envoyez-les à une seule requête d’API à Databricks VisionModel. Le modèle traite toutes les images simultanément et retourne des légendes pour l’ensemble du lot.
- La
terminateméthode est exécutée exactement une fois à la fin de chaque partition. Dans la méthode terminate, traitez les images restantes dans la mémoire tampon et fournissez toutes les descriptions collectées sous forme de résultats.
Note
Remplacez <workspace-url> par votre URL d’espace de travail Azure Databricks réelle (https://your-workspace.cloud.databricks.com).
CREATE OR REPLACE TEMPORARY FUNCTION batch_inference_image_caption(data TABLE, api_token STRING)
RETURNS TABLE (caption STRING)
LANGUAGE PYTHON
HANDLER 'BatchInferenceImageCaption'
COMMENT 'batch image captioning by sending groups of image URLs to a Databricks vision endpoint and returning concise captions for each image.'
AS $$
class BatchInferenceImageCaption:
def __init__(self):
self.batch_size = 3
self.vision_endpoint = "databricks-claude-sonnet-4-5"
self.workspace_url = "<workspace-url>"
self.image_buffer = []
self.results = []
def eval(self, row, api_token):
self.image_buffer.append((str(row[0]), api_token))
if len(self.image_buffer) >= self.batch_size:
self._process_batch()
def terminate(self):
if self.image_buffer:
self._process_batch()
for caption in self.results:
yield (caption,)
def _process_batch(self):
batch_data = self.image_buffer.copy()
self.image_buffer.clear()
import base64
import httpx
import requests
# API request timeout in seconds
api_timeout = 60
# Maximum tokens for vision model response
max_response_tokens = 300
# Temperature controls randomness (lower = more deterministic)
model_temperature = 0.3
# create a batch for the images
batch_images = []
api_token = batch_data[0][1] if batch_data else None
for image_url, _ in batch_data:
image_response = httpx.get(image_url, timeout=15)
image_data = base64.standard_b64encode(image_response.content).decode("utf-8")
batch_images.append(image_data)
content_items = [{
"type": "text",
"text": "Provide brief captions for these images, one per line."
}]
for img_data in batch_images:
content_items.append({
"type": "image_url",
"image_url": {
"url": "data:image/jpeg;base64," + img_data
}
})
payload = {
"messages": [{
"role": "user",
"content": content_items
}],
"max_tokens": max_response_tokens,
"temperature": model_temperature
}
response = requests.post(
self.workspace_url + "/serving-endpoints/" +
self.vision_endpoint + "/invocations",
headers={
'Authorization': 'Bearer ' + api_token,
'Content-Type': 'application/json'
},
json=payload,
timeout=api_timeout
)
result = response.json()
batch_response = result['choices'][0]['message']['content'].strip()
lines = batch_response.split('\n')
captions = [line.strip() for line in lines if line.strip()]
while len(captions) < len(batch_data):
captions.append(batch_response)
self.results.extend(captions[:len(batch_data)])
$$;
Pour utiliser l'UDTF de légendage d'image par lots, appelez-le en l'appelant avec la table d'exemples d'images.
Note
Remplacez your_secret_scope et api_token par l’étendue secrète et le nom de clé réels pour le jeton d’API Databricks.
SELECT
caption
FROM
batch_inference_image_caption(
data => TABLE(sample_images),
api_token => secret('your_secret_scope', 'api_token')
)
+---------------------------------------------------------------------------------------------------------------+
| caption |
+---------------------------------------------------------------------------------------------------------------+
| Wooden boardwalk cutting through vibrant wetland grasses under blue skies |
| Black ant in detailed macro photography standing on a textured surface |
| Tabby cat lounging comfortably on a white ledge against a white wall |
| Stunning spiral galaxy with bright central core and sweeping blue-white arms against the black void of space. |
+---------------------------------------------------------------------------------------------------------------+
Vous pouvez également générer une catégorie de légendes d’image par catégorie :
SELECT
*
FROM
batch_inference_image_caption(
TABLE(sample_images)
PARTITION BY category ORDER BY (category),
secret('your_secret_scope', 'api_token')
)
+------------------------------------------------------------------------------------------------------+
| caption |
+------------------------------------------------------------------------------------------------------+
| Black ant in detailed macro photography standing on a textured surface |
| Stunning spiral galaxy with bright center and sweeping blue-tinged arms against the black of space. |
| Tabby cat lounging comfortably on white ledge against white wall |
| Wooden boardwalk cutting through lush wetland grasses under blue skies |
+------------------------------------------------------------------------------------------------------+
Exemple : calcul de courbe ROC et d’AUC pour l’évaluation du modèle ML
Cet exemple illustre le calcul des courbes ROC (Receiver Operating Characteristic) et des scores AUC (Area Under the Curve) pour l'évaluation des modèles de classification binaire à l'aide de scikit-learn.
Cet exemple présente plusieurs modèles importants :
- Utilisation de la bibliothèque externe : intègre scikit-learn pour le calcul de courbe ROC
- Agrégation avec état : accumule les prédictions pour toutes les lignes avant le calcul des métriques
-
terminate()utilisation des méthodes : traite le jeu de données complet et génère des résultats uniquement après que toutes les lignes ont été évaluées - Gestion des erreurs : valide les colonnes requises dans la table d’entrée
L’UDTF accumule toutes les prédictions en mémoire à l’aide de la eval() méthode, puis calcule et génère la courbe ROC complète dans la terminate() méthode. Ce modèle est utile pour les métriques qui nécessitent le jeu de données complet pour le calcul.
CREATE OR REPLACE TEMPORARY FUNCTION compute_roc_curve(t TABLE)
RETURNS TABLE (threshold DOUBLE, true_positive_rate DOUBLE, false_positive_rate DOUBLE, auc DOUBLE)
LANGUAGE PYTHON
HANDLER 'ROCCalculator'
COMMENT 'Compute ROC curve and AUC using scikit-learn'
AS $$
class ROCCalculator:
def __init__(self):
from sklearn import metrics
self._roc_curve = metrics.roc_curve
self._roc_auc_score = metrics.roc_auc_score
self._true_labels = []
self._predicted_scores = []
def eval(self, row):
if 'y_true' not in row or 'y_score' not in row:
raise KeyError("Required columns 'y_true' and 'y_score' not found")
true_label = row['y_true']
predicted_score = row['y_score']
label = float(true_label)
self._true_labels.append(label)
self._predicted_scores.append(float(predicted_score))
def terminate(self):
false_pos_rate, true_pos_rate, thresholds = self._roc_curve(
self._true_labels,
self._predicted_scores,
drop_intermediate=False
)
auc_score = float(self._roc_auc_score(self._true_labels, self._predicted_scores))
for threshold, tpr, fpr in zip(thresholds, true_pos_rate, false_pos_rate):
yield float(threshold), float(tpr), float(fpr), auc_score
$$;
Créez des exemples de données de classification binaire avec des prédictions :
CREATE OR REPLACE TEMPORARY VIEW binary_classification_data AS
SELECT *
FROM VALUES
( 1, 1.0, 0.95, 'high_confidence_positive'),
( 2, 1.0, 0.87, 'high_confidence_positive'),
( 3, 1.0, 0.82, 'medium_confidence_positive'),
( 4, 0.0, 0.78, 'false_positive'),
( 5, 1.0, 0.71, 'medium_confidence_positive'),
( 6, 0.0, 0.65, 'false_positive'),
( 7, 0.0, 0.58, 'true_negative'),
( 8, 1.0, 0.52, 'low_confidence_positive'),
( 9, 0.0, 0.45, 'true_negative'),
(10, 0.0, 0.38, 'true_negative'),
(11, 1.0, 0.31, 'low_confidence_positive'),
(12, 0.0, 0.15, 'true_negative'),
(13, 0.0, 0.08, 'high_confidence_negative'),
(14, 0.0, 0.03, 'high_confidence_negative')
AS data(sample_id, y_true, y_score, prediction_type);
Calculez la courbe ROC et l’AUC :
SELECT
threshold,
true_positive_rate,
false_positive_rate,
auc
FROM compute_roc_curve(
TABLE(
SELECT y_true, y_score
FROM binary_classification_data
WHERE y_true IS NOT NULL AND y_score IS NOT NULL
ORDER BY sample_id
)
)
ORDER BY threshold DESC;
+-----------+---------------------+----------------------+-------+
| threshold | true_positive_rate | false_positive_rate | auc |
+-----------+---------------------+----------------------+-------+
| 1.95 | 0.0 | 0.0 | 0.786 |
| 0.95 | 0.167 | 0.0 | 0.786 |
| 0.87 | 0.333 | 0.0 | 0.786 |
| 0.82 | 0.5 | 0.0 | 0.786 |
| 0.78 | 0.5 | 0.125 | 0.786 |
| 0.71 | 0.667 | 0.125 | 0.786 |
| 0.65 | 0.667 | 0.25 | 0.786 |
| 0.58 | 0.667 | 0.375 | 0.786 |
| 0.52 | 0.833 | 0.375 | 0.786 |
| 0.45 | 0.833 | 0.5 | 0.786 |
| 0.38 | 0.833 | 0.625 | 0.786 |
| 0.31 | 1.0 | 0.625 | 0.786 |
| 0.15 | 1.0 | 0.75 | 0.786 |
| 0.08 | 1.0 | 0.875 | 0.786 |
| 0.03 | 1.0 | 1.0 | 0.786 |
+-----------+---------------------+----------------------+-------+
Limites
Les limitations suivantes s’appliquent aux fonctions définies par l’utilisateur python du catalogue Unity :
- Les fonctions de table polymorphes ne sont pas prises en charge.
- Les informations d’identification du service catalogue Unity ne sont pas prises en charge.
- Les dépendances personnalisées ne sont pas prises en charge.