Delen via


Schalen om meer geregistreerde gebruikers af te handelen

Let op

Toegang tot face-services is beperkt op basis van geschiktheids- en gebruikscriteria om onze verantwoorde AI-principes te ondersteunen. Face-service is alleen beschikbaar voor door Microsoft beheerde klanten en partners. Gebruik het intakeformulier voor gezichtsherkenning om toegang aan te vragen. Zie de pagina beperkte toegang van Face voor meer informatie.

In deze handleiding ziet u hoe u omhoog kunt schalen van bestaande PersonGroup - en FaceList-objecten naar LargePersonGroup - en LargeFaceList-objecten . PersonGroups kan maximaal 1000 personen bevatten in de gratis laag en 10.000 in de betaalde laag, terwijl LargePersonGroups maximaal één miljoen personen in de betaalde laag kan bevatten.

Belangrijk

De nieuwere gegevensstructuur PersonDirectory wordt aanbevolen voor nieuwe ontwikkeling. Het kan maximaal 75 miljoen identiteiten bevatten en vereist geen handmatige training. Zie de handleiding PersonDirectory voor meer informatie.

In deze handleiding wordt het migratieproces gedemonstreerd. Hierbij wordt ervan uitgegaan dat u bekend bent met PersonGroup- en FaceList-objecten, de trainbewerking en de gezichtsherkenningsfuncties. Zie de conceptuele handleiding voor gezichtsherkenning voor meer informatie over deze onderwerpen.

LargePersonGroup en LargeFaceList worden gezamenlijk grootschalige bewerkingen genoemd. LargePersonGroup kan maximaal 1 miljoen personen bevatten, elk met een maximum van 248 gezichten. LargeFaceList kan maximaal 1 miljoen gezichten bevatten. De grootschalige bewerkingen zijn vergelijkbaar met de conventionele PersonGroup en FaceList , maar hebben enkele verschillen vanwege de nieuwe architectuur.

De voorbeelden zijn geschreven in C#.

Notitie

Als u facezoekprestaties voor Identificatie en FindSimilar in grote schaal wilt inschakelen, introduceert u een trainbewerking om de LargeFaceList en LargePersonGroup vooraf te verwerken. De trainingstijd varieert van seconden tot ongeveer een half uur, al naargelang de werkelijke capaciteit. Tijdens de trainingsperiode is het mogelijk om Identification en FindSimilar uit te voeren als er eerder een succesvolle training is uitgevoerd. Het nadeel is dat de nieuw toegevoegde personen/gezichten pas worden weergegeven in het resultaat als er een nieuwe grootschalige training na de migratie is uitgevoerd.

Stap 1: Codemigratie

In deze sectie wordt uitgelegd hoe u de implementatie van PersonGroup of FaceList migreert naar LargePersonGroup of LargeFaceList. Hoewel LargePersonGroup of LargeFaceList verschilt van PersonGroup of FaceList in ontwerp en interne implementatie, zijn de API-interfaces vergelijkbaar voor compatibiliteit met eerdere versies.

Gegevensmigratie wordt niet ondersteund. U maakt in plaats daarvan de LargePersonGroup of LargeFaceList opnieuw.

Een PersonGroup migreren naar een LargePersonGroup

Migratie van een PersonGroup naar een LargePersonGroup is eenvoudig. Ze delen precies dezelfde bewerkingen op groepsniveau.

Voor personGroup of person-gerelateerde implementatie is het noodzakelijk om alleen de API-paden of SDK-klasse/module te wijzigen in LargePersonGroup en LargePersonGroup Person.

Voeg alle gezichten en personen van de PersonGroup toe aan de nieuwe LargePersonGroup. Zie Gezichten toevoegen voor meer informatie.

Een FaceList migreren naar een LargeFaceList

FaceList-API's LargeFaceList-API's
Maken Maken
Verwijderen Delete
Ophalen Ophalen
List List
Bijwerken Bijwerken
- Trainen
- Trainingsstatus ophalen

De voorgaande tabel is een vergelijking van bewerkingen op lijstniveau tussen FaceList en LargeFaceList. Zoals wordt weergegeven, wordt LargeFaceList geleverd met nieuwe bewerkingen, Train and Get Training Status, in vergelijking met FaceList. De LargeFaceList trainen is een voorwaarde voor de Bewerking FindSimilar. Training is niet vereist voor FaceList. Het volgende codefragment is een helperfunctie om te wachten op de training van een LargeFaceList:

/// <summary>
/// Helper function to train LargeFaceList and wait for finish.
/// </summary>
/// <remarks>
/// The time interval can be adjusted considering the following factors:
/// - The training time which depends on the capacity of the LargeFaceList.
/// - The acceptable latency for getting the training status.
/// - The call frequency and cost.
///
/// Estimated training time for LargeFaceList in different scale:
/// -     1,000 faces cost about  1 to  2 seconds.
/// -    10,000 faces cost about  5 to 10 seconds.
/// -   100,000 faces cost about  1 to  2 minutes.
/// - 1,000,000 faces cost about 10 to 30 minutes.
/// </remarks>
/// <param name="largeFaceListId">The Id of the LargeFaceList for training.</param>
/// <param name="timeIntervalInMilliseconds">The time interval for getting training status in milliseconds.</param>
/// <returns>A task of waiting for LargeFaceList training finish.</returns>
private static async Task TrainLargeFaceList(
    string largeFaceListId,
    int timeIntervalInMilliseconds = 1000)
{
    HttpClient httpClient = new HttpClient();
    httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", SUBSCRIPTION_KEY);

    // Trigger a train call.
    await httpClient.PostAsync($"{ENDPOINT}/face/v1.0/largefacelists/{largeFaceListId}/train", null);

    // Wait for training finish.
    while (true)
    {
        await Task.Delay(timeIntervalInMilliseconds);
        string? trainingStatus = null;
        using (var response = await httpClient.GetAsync($"{ENDPOINT}/face/v1.0/largefacelists/{largeFaceListId}/training"))
        {
            string contentString = await response.Content.ReadAsStringAsync();
            trainingStatus = (string?)(JsonConvert.DeserializeObject<Dictionary<string, object>>(contentString)?["status"]);
        }

        if ("running".Equals(trainingStatus))
        {
            continue;
        }
        else if ("succeeded".Equals(trainingStatus))
        {
            break;
        }
        else
        {
            throw new Exception("The train operation is failed!");
        }
    }
}

Voorheen leek een typisch gebruik van FaceList met toegevoegde gezichten en FindSimilar er als volgt uit:

// Create a FaceList.
const string FaceListId = "myfacelistid_001";
const string FaceListName = "MyFaceListDisplayName";
const string ImageDir = @"/path/to/FaceList/images";
using (var content = new ByteArrayContent(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Dictionary<string, object> { ["name"] = FaceListName, ["recognitionModel"] = "recognition_04" }))))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    await httpClient.PutAsync($"{ENDPOINT}/face/v1.0/facelists/{FaceListId}", content);
}

// Add Faces to the FaceList.
Parallel.ForEach(
    Directory.GetFiles(ImageDir, "*.jpg"),
    async imagePath =>
    {
        using (Stream stream = File.OpenRead(imagePath))
        {
            using (var content = new StreamContent(stream))
            {
                content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                await httpClient.PostAsync($"{ENDPOINT}/face/v1.0/facelists/{FaceListId}/persistedfaces?detectionModel=detection_03", content);
            }
        }
    });

// Perform FindSimilar.
const string QueryImagePath = @"/path/to/query/image";
var results = new List<HttpResponseMessage>();
using (Stream stream = File.OpenRead(QueryImagePath))
{
    var response = await faceClient.DetectAsync(BinaryData.FromStream(stream), FaceDetectionModel.Detection03, FaceRecognitionModel.Recognition04, returnFaceId: true);
    var faces = response.Value;
    foreach (var face in faces)
    {
        using (var content = new ByteArrayContent(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Dictionary<string, object> { ["faceId"] = face.FaceId, ["faceListId"] = FaceListId }))))
        {
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            results.Add(await httpClient.PostAsync($"{ENDPOINT}/face/v1.0/findsimilars", content));
        }
    }
}

Wanneer u deze migreert naar LargeFaceList, wordt het volgende:

// Create a LargeFaceList.
const string LargeFaceListId = "mylargefacelistid_001";
const string LargeFaceListName = "MyLargeFaceListDisplayName";
const string ImageDir = @"/path/to/FaceList/images";
using (var content = new ByteArrayContent(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Dictionary<string, object> { ["name"] = LargeFaceListName, ["recognitionModel"] = "recognition_04" }))))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    await httpClient.PutAsync($"{ENDPOINT}/face/v1.0/largefacelists/{LargeFaceListId}", content);
}

// Add Faces to the LargeFaceList.
Parallel.ForEach(
    Directory.GetFiles(ImageDir, "*.jpg"),
    async imagePath =>
    {
        using (Stream stream = File.OpenRead(imagePath))
        {
            using (var content = new StreamContent(stream))
            {
                content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                await httpClient.PostAsync($"{ENDPOINT}/face/v1.0/largefacelists/{LargeFaceListId}/persistedfaces?detectionModel=detection_03", content);
            }
        }
    });

// Train() is newly added operation for LargeFaceList.
// Must call it before FindSimilar to ensure the newly added faces searchable.
await TrainLargeFaceList(LargeFaceListId);

// Perform FindSimilar.
const string QueryImagePath = @"/path/to/query/image";
var results = new List<HttpResponseMessage>();
using (Stream stream = File.OpenRead(QueryImagePath))
{
    var response = await faceClient.DetectAsync(BinaryData.FromStream(stream), FaceDetectionModel.Detection03, FaceRecognitionModel.Recognition04, returnFaceId: true);
    var faces = response.Value;
    foreach (var face in faces)
    {
        using (var content = new ByteArrayContent(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Dictionary<string, object> { ["faceId"] = face.FaceId, ["largeFaceListId"] = LargeFaceListId }))))
        {
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            results.Add(await httpClient.PostAsync($"{ENDPOINT}/face/v1.0/findsimilars", content));
        }
    }
}

Zoals eerder is weergegeven, zijn het gegevensbeheer en het onderdeel FindSimilar bijna hetzelfde. De enige uitzondering hierop is dat een nieuwe voorverwerkingsbewerking Train moet worden voltooid in LargeFaceList voordat FindSimilar werkt.

Stap 2: Suggesties trainen

Hoewel de Train-bewerking FindSimilar en Identification versnelt, lijdt de trainingstijd, vooral bij grote schaal. De geschatte trainingstijd in verschillende schalen wordt in de volgende tabel vermeld.

Schaal voor gezichten of personen Geschatte trainingstijd
1.000 1-2 sec.
10,000 5-10 sec.
100.000 1-2 min.
1.000.000 10-30 min.

We raden u aan de volgende strategieën te gebruiken om de functie voor een grote schaal beter te benutten.

Stap 2a: tijdsinterval aanpassen

Zoals wordt weergegeven in TrainLargeFaceList(), is er een tijdsinterval in milliseconden om het oneindige proces voor controle van de trainingsstatus uit te stellen. Voor LargeFaceList met meer gezichten vermindert het gebruik van een groter interval het aantal aanroepen en de kosten. Pas het tijdsinterval aan op basis van de verwachte capaciteit van de LargeFaceList.

Dezelfde strategie geldt ook voor LargePersonGroup. Wanneer u bijvoorbeeld een LargePersonGroup traint met 1 miljoen personen, timeIntervalInMilliseconds kan dit 60.000 zijn, wat een interval van 1 minuut is.

Stap 2b: Kleinschalige buffer

Personen of gezichten in een LargePersonGroup of een LargeFaceList kunnen pas worden doorzocht nadat ze zijn getraind. In een dynamisch scenario worden voortdurend nieuwe personen of gezichten toegevoegd, die onmiddellijk doorzoekbaar moeten zijn, maar de training kan langer duren dan gewenst.

Als u dit probleem wilt verhelpen, gebruikt u een extra kleinschalige LargePersonGroup of LargeFaceList als buffer voor de zojuist toegevoegde vermeldingen. Deze buffer kan sneller worden getraind vanwege de beperkte grootte. De functie voor onmiddellijke doorzoekbaarheid zou moeten werken voor deze tijdelijke buffer. Gebruik deze buffer in combinatie met training op de master LargePersonGroup of LargeFaceList door de mastertraining op een sparserinterval uit te voeren. Bijvoorbeeld dagelijks om middernacht.

Voorbeeld van een werkstroom:

  1. Maak een master LargePersonGroup of LargeFaceList, de hoofdverzameling. Maak een buffer LargePersonGroup of LargeFaceList, de bufferverzameling. De bufferverzameling is alleen voor nieuw toegevoegde personen of gezichten.
  2. Voeg nieuwe personen of gezichten toe aan zowel de masterverzameling als de bufferverzameling.
  3. Train alleen de bufferverzameling met een kort interval om te waarborgen dat de zojuist toegevoegde vermeldingen bruikbaar zijn.
  4. Roep Identification of FindSimilar aan voor zowel de hoofdverzameling als de bufferverzameling. Voeg de resultaten samen.
  5. Wanneer de omvang van de bufferverzameling een drempelwaarde bereikt, of op een tijd dat het systeem niet actief is, maakt u een nieuwe bufferverzameling. Activeer de trainbewerking op de hoofdverzameling.
  6. Verwijder de oude bufferverzameling nadat de trainbewerking is voltooid op de hoofdverzameling.

Stap 2c: Zelfstandige training

Als een relatief lange latentie acceptabel is, is het niet nodig om de trainbewerking te activeren direct nadat u nieuwe gegevens hebt toegevoegd. In plaats daarvan kan de trainbewerking worden gesplitst van de hoofdlogica en regelmatig worden geactiveerd. Deze strategie is geschikt voor dynamische scenario's met een acceptabele latentie. Het kan worden toegepast op statische scenario's om de frequentie van de trein verder te verminderen.

Stel dat er een TrainLargePersonGroup-functie is die vergelijkbaar is met TrainLargeFaceList. Een typische implementatie van de zelfstandige training op een LargePersonGroup door de Timer klasse aan System.Timers te roepen is:

private static void Main()
{
    // Set up standalone training at regular intervals.
    const int TimeIntervalForStatus = 1000 * 60; // 1-minute interval for getting training status.
    const double TimeIntervalForTrain = 1000 * 60 * 60; // 1-hour interval for training.
    var trainTimer = new Timer(TimeIntervalForTrain);
    trainTimer.Elapsed += (sender, args) => TrainTimerOnElapsed("mylargepersongroupid_001", TimeIntervalForStatus);
    trainTimer.AutoReset = true;
    trainTimer.Enabled = true;

    // Other operations like creating persons, adding faces, and identification, except for Train.
    // ...
}

private static void TrainTimerOnElapsed(string largePersonGroupId, int timeIntervalInMilliseconds)
{
    TrainLargePersonGroup(largePersonGroupId, timeIntervalInMilliseconds).Wait();
}

Zie Gezichten toevoegen voor meer informatie over gegevensbeheer en aan identificatie gerelateerde implementaties.

Samenvatting

In deze handleiding hebt u geleerd hoe u de bestaande PersonGroup- of FaceList-code, niet gegevens, migreert naar largePersonGroup of LargeFaceList:

  • LargePersonGroup en LargeFaceList werken vergelijkbaar met PersonGroup of FaceList, behalve dat de trainbewerking is vereist voor LargeFaceList.
  • Neem de juiste trainstrategie voor dynamische gegevensupdates voor grootschalige gegevenssets.

Volgende stappen

Volg een handleiding voor meer informatie over het toevoegen van gezichten aan een PersonGroup of het schrijven van een script om de bewerking Identificeren in een PersonGroup uit te voeren.