Exempel: Använda den storskaliga funktionen

Den här guiden är en avancerad artikel om hur du skalar upp från befintliga PersonGroup- och FaceList-objekt till LargePersonGroup- respektive LargeFaceList-objekt. Den här guiden visar migreringsprocessen. Den förutsätter grundläggande kunskaper om PersonGroup- och FaceList-objekt, åtgärden Träna och funktionerna för ansiktsigenkänning. Mer information om de här ämnena finns i konceptuell guide för ansiktsigenkänning.

LargePersonGroup och LargeFaceList kallas gemensamt för storskaliga åtgärder. LargePersonGroup kan innehålla upp till 1 miljon personer, var och en med högst 248 ansikten. LargeFaceList kan innehålla upp till 1 miljon ansikten. Storskaliga åtgärder liknar konventionella PersonGroup och FaceList men har vissa skillnader på grund av den nya arkitekturen.

Exemplen är skrivna i C# med hjälp Azure Cognitive Services klientbiblioteket för ansikts-face.

Anteckning

Om du vill aktivera ansiktssökningsprestanda för identifiering och FindSimilar i stor skala, introducerar du en train-åtgärd för att förbearbeta LargeFaceList och LargePersonGroup. Träningstiden varierar från sekunder till ungefär en halvtimme baserat på den faktiska kapaciteten. Under träningsperioden är det möjligt att utföra identifiering och FindSimilar om en lyckad träning har utförts tidigare. Nackdelen är att de nya tillagda personerna och ansiktena inte visas i resultatet förrän en ny eftermigrering till storskalig träning har slutförts.

Steg 1: Initiera klientobjektet

När du använder ansiktsklientbiblioteket skickas prenumerationsnyckeln och prenumerationsslutpunkten via konstruktorn för klassen FaceClient. Exempel:

string SubscriptionKey = "<Subscription Key>";
// Use your own subscription endpoint corresponding to the subscription key.
string SubscriptionEndpoint = "https://westus.api.cognitive.microsoft.com";
private readonly IFaceClient faceClient = new FaceClient(
            new ApiKeyServiceClientCredentials(subscriptionKey),
            new System.Net.Http.DelegatingHandler[] { });
faceClient.Endpoint = SubscriptionEndpoint

Om du vill hämta prenumerationsnyckeln med motsvarande slutpunkt går du till Azure Marketplace från Azure Portal. Mer information finns i Prenumerationer.

Steg 2: Kodmigrering

Det här avsnittet fokuserar på hur du migrerar PersonGroup- eller FaceList-implementering till LargePersonGroup eller LargeFaceList. Även om LargePersonGroup eller LargeFaceList skiljer sig från PersonGroup eller FaceList i design och intern implementering, är API-gränssnitten liknande för bakåtkompatibilitet.

Datamigrering stöds inte. Du skapar om LargePersonGroup eller LargeFaceList i stället.

Migrera en PersonGroup till en LargePersonGroup

Det är enkelt att migrera från en PersonGroup till en LargePersonGroup. De delar exakt samma åtgärder på gruppnivå.

För PersonGroup- eller personrelaterad implementering är det nödvändigt att bara ändra API-sökvägarna eller SDK-klassen/-modulen till LargePersonGroup och LargePersonGroup Person.

Lägg till alla ansikten och personer från PersonGroup till den nya LargePersonGroup. Mer information finns i Lägga till ansikten.

Migrera en FaceList till en LargeFaceList

FaceList API:er LargeFaceList API:er
Skapa Skapa
Ta bort Ta bort
Hämta Hämta
Lista Lista
Uppdatera Uppdatera
- Träna
- Hämta träningsstatus

Föregående tabell är en jämförelse av åtgärder på listnivå mellan FaceList och LargeFaceList. Som visas levereras LargeFaceList med nya åtgärder, Träna och Hämta träningsstatus, jämfört med FaceList. Träning av LargeFaceList är ett förhandsvillkor för FindSimilar-åtgärden. Träning krävs inte för FaceList. Följande kodfragment är en hjälpfunktion som väntar på träning av en 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)
{
    // Trigger a train call.
    await FaceClient.LargeTrainLargeFaceListAsync(largeFaceListId);

    // Wait for training finish.
    while (true)
    {
        Task.Delay(timeIntervalInMilliseconds).Wait();
        var status = await faceClient.LargeFaceList.TrainAsync(largeFaceListId);

        if (status.Status == Status.Running)
        {
            continue;
        }
        else if (status.Status == Status.Succeeded)
        {
            break;
        }
        else
        {
            throw new Exception("The train operation is failed!");
        }
    }
}

Tidigare såg en typisk användning av FaceList med tillagda ansikten och FindSimilar ut så här:

// Create a FaceList.
const string FaceListId = "myfacelistid_001";
const string FaceListName = "MyFaceListDisplayName";
const string ImageDir = @"/path/to/FaceList/images";
faceClient.FaceList.CreateAsync(FaceListId, FaceListName).Wait();

// Add Faces to the FaceList.
Parallel.ForEach(
    Directory.GetFiles(ImageDir, "*.jpg"),
    async imagePath =>
        {
            using (Stream stream = File.OpenRead(imagePath))
            {
                await faceClient.FaceList.AddFaceFromStreamAsync(FaceListId, stream);
            }
        });

// Perform FindSimilar.
const string QueryImagePath = @"/path/to/query/image";
var results = new List<SimilarPersistedFace[]>();
using (Stream stream = File.OpenRead(QueryImagePath))
{
    var faces = faceClient.Face.DetectWithStreamAsync(stream).Result;
    foreach (var face in faces)
    {
        results.Add(await faceClient.Face.FindSimilarAsync(face.FaceId, FaceListId, 20));
    }
}

När du migrerar den till LargeFaceList blir den följande:

// Create a LargeFaceList.
const string LargeFaceListId = "mylargefacelistid_001";
const string LargeFaceListName = "MyLargeFaceListDisplayName";
const string ImageDir = @"/path/to/FaceList/images";
faceClient.LargeFaceList.CreateAsync(LargeFaceListId, LargeFaceListName).Wait();

// Add Faces to the LargeFaceList.
Parallel.ForEach(
    Directory.GetFiles(ImageDir, "*.jpg"),
    async imagePath =>
        {
            using (Stream stream = File.OpenRead(imagePath))
            {
                await faceClient.LargeFaceList.AddFaceFromStreamAsync(LargeFaceListId, stream);
            }
        });

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

// Perform FindSimilar.
const string QueryImagePath = @"/path/to/query/image";
var results = new List<SimilarPersistedFace[]>();
using (Stream stream = File.OpenRead(QueryImagePath))
{
    var faces = faceClient.Face.DetectWithStreamAsync(stream).Result;
    foreach (var face in faces)
    {
        results.Add(await faceClient.Face.FindSimilarAsync(face.FaceId, largeFaceListId: LargeFaceListId));
    }
}

Som tidigare visat är datahanteringen och FindSimilar-delen nästan desamma. Det enda undantaget är att en ny förbearbetningsåtgärd för train måste slutföras i LargeFaceList innan FindSimilar fungerar.

Steg 3: Träna förslag

Även om träningsåtgärden påskyndar FindSimilar och identifieringså drabbas träningstiden, särskilt när det kommer till stor skala. Den uppskattade träningstiden i olika skalor visas i följande tabell.

Skala för ansikten eller personer Uppskattad träningstid
1 000 1–2 sek
10 000 5–10 sek
100 000 1–2 min
1,000,000 10–30 min

Om du vill använda den storskaliga funktionen på ett bättre sätt rekommenderar vi följande strategier.

Steg 3.1: Anpassa tidsintervallet

Som du ser i finns det ett tidsintervall i millisekunder för att fördröja den oändliga statuskontrollen TrainLargeFaceList() för träning. För LargeFaceList med flera ansikten, minskar anropsantalet och -kostnaden med hjälp av ett större intervall. Anpassa tidsintervallet enligt den förväntade kapaciteten för LargeFaceList.

Samma strategi gäller även för LargePersonGroup. När du till exempel tränar en LargePersonGroup med 1 miljon personer kan det vara timeIntervalInMilliseconds 60 000, vilket är ett intervall på 1 minut.

Steg 3.2: Småskalig buffert

Personer eller ansikten i en LargePersonGroup eller en LargeFaceList är sökbara först efter att de har tränats. I ett dynamiskt scenario läggs nya personer eller ansikten hela tiden till och måste vara omedelbart sökbara, men träningen kan ta längre tid än vad som önskas.

För att åtgärda det här problemet använder du en extra småskalig LargePersonGroup eller LargeFaceList som en buffert endast för de nyligen tillagda posterna. Den här bufferten tar en kortare tid att träna på grund av den mindre storleken. Den omedelbara sökfunktionen i den här tillfälliga bufferten bör fungera. Använd den här bufferten i kombination med träning på huvuddatorn LargePersonGroup eller LargeFaceList genom att köra masterträningen med ett sparserintervall. Exempel är mitt i natten och dagligen.

Ett exempel på ett arbetsflöde:

  1. Skapa en LargePersonGroup eller LargeFaceList som är huvudsamlingen. Skapa en buffert för LargePersonGroup eller LargeFaceList, som är buffertsamlingen. Buffertsamlingen är endast för nyligen tillagda personer eller ansikten.
  2. Lägg till nya personer eller ansikten i både huvudsamlingen och buffertsamlingen.
  3. Träna bara buffertsamlingen med ett kort tidsintervall för att säkerställa att de nyligen tillagda posterna gäller.
  4. Anropa identifiering eller FindSimilar mot både huvudsamlingen och buffertsamlingen. Sammanslå resultaten.
  5. När buffertsamlingens storlek ökar till ett tröskelvärde eller vid inaktivitet i systemet skapar du en ny buffertsamling. Utlösningsåtgärden Train (Träna) i huvudsamlingen.
  6. Ta bort den gamla buffertsamlingen när åtgärden Train har avslutats på huvudsamlingen.

Steg 3.3: Fristående träning

Om en relativt lång svarstid är acceptabel behöver du inte utlösa åtgärden Träna direkt efter att du har lagt till nya data. Istället kan träningsåtgärden delas upp från den huvudsakliga logiken och utlösas regelbundet. Den här strategin är lämplig för dynamiska scenarier med acceptabel svarstid. Det kan tillämpas på statiska scenarier för att ytterligare minska frekvensen för träna.

Anta att det finns en TrainLargePersonGroup funktion som liknar TrainLargeFaceList . En typisk implementering av den fristående träningen på en LargePersonGroup genom att anropa Timer klassen i System.Timers är:

private static void Main()
{
    // Create a LargePersonGroup.
    const string LargePersonGroupId = "mylargepersongroupid_001";
    const string LargePersonGroupName = "MyLargePersonGroupDisplayName";
    faceClient.LargePersonGroup.CreateAsync(LargePersonGroupId, LargePersonGroupName).Wait();

    // 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(LargePersonGroupId, 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();
}

Mer information om datahantering och identifieringsrelaterade implementeringar finns i Lägga till ansikten.

Sammanfattning

I den här guiden har du lärt dig hur du migrerar befintlig PersonGroup- eller FaceList-kod, inte data, till LargePersonGroup eller LargeFaceList:

  • LargePersonGroup och LargeFaceList fungerar ungefär som PersonGroup eller FaceList, förutom att åtgärden Train krävs av LargeFaceList.
  • Ta rätt träna strategi för dynamisk datauppdatering för storskaliga datauppsättningar.

Nästa steg

Följ en guide för att lära dig hur du lägger till ansikten i en PersonGroup eller skriver ett skript för att göra identifieringsåtgärden på en PersonGroup.