Škálování pro zpracování více zaregistrovaných uživatelů
Upozornění
Přístup ke službě Rozpoznávání tváře je omezený na základě kritérií způsobilosti a použití, aby bylo možné podporovat naše zásady zodpovědné umělé inteligence. Služba Rozpoznávání tváře je dostupná jenom pro zákazníky a partnery spravované Microsoftem. Pro přístup použijte formulář pro příjem rozpoznávání tváře. Další informace najdete na stránce s omezeným přístupem k tváři.
V této příručce se dozvíte, jak vertikálně navýšit kapacitu z existujících objektů PersonGroup a FaceList na objekty LargePersonGroup a LargeFaceList . Skupiny PersonGroup mohou mít až 1 000 osob na úrovni Free a 10 000 na placené úrovni, zatímco Skupiny LargePersonGroup mohou mít až jeden milion osob na placené úrovni.
Důležité
Pro nový vývoj se doporučuje novější datová struktura PersonDirectory . Může obsahovat až 20 milionů identit a nevyžaduje ruční trénování. Další informace najdete v příručce PersonDirectory.
Tento průvodce ukazuje proces migrace. Předpokládá základní znalost objektů PersonGroup a FaceList , operace Train a funkce rozpoznávání tváře. Další informace o těchto tématech najdete v koncepčním průvodci rozpoznáváním tváře.
LargePersonGroup a LargeFaceList se souhrnně označují jako rozsáhlé operace. LargePersonGroup může obsahovat až 1 milion osob, z nichž každý má maximálně 248 tváří. LargeFaceList může obsahovat až 1 milion tváří. Rozsáhlé operace se podobají konvenční skupině PersonGroup a FaceList , ale vzhledem k nové architektuře mají určité rozdíly.
Ukázky jsou napsané v jazyce C#.
Poznámka:
Pokud chcete povolit výkon vyhledávání tváří pro identifikaci a FindSimilar ve velkém měřítku, zavedněte operaci Train pro předběžné zpracování LargeFaceList a LargePersonGroup. Doba trénování se v závislosti na skutečné kapacitě liší od sekund po přibližně půl hodiny. Během trénovacího období je možné provést identifikaci a najítSimilar , pokud bylo úspěšné trénování provedeno dříve. Nevýhodou je, že nové přidané osoby a tváře se ve výsledku nezobrazí, dokud se nedokončí nová migrace na rozsáhlé trénování.
Krok 1: Migrace kódu
Tato část se zaměřuje na migraci implementace PersonGroup nebo FaceList do LargePersonGroup nebo LargeFaceList. I když se LargePersonGroup a LargeFaceList liší od PersonGroup a FaceList v návrhu a interní implementaci, rozhraní API jsou podobná zpětné kompatibilitě.
Migrace dat se nepodporuje. Místo toho znovu vytvoříte LargePersonGroup nebo LargeFaceList .
Migrace skupiny PersonGroup do LargePersonGroup
Migrace ze skupiny PersonGroup do LargePersonGroup je jednoduchá. Sdílejí přesně stejné operace na úrovni skupiny.
U implementace PersonGroup nebo person-related je nutné změnit pouze cesty rozhraní API nebo třídy nebo modulu SDK na LargePersonGroup a LargePersonGroupPerson.
Přidejte do nové skupiny LargePersonGroup všechny tváře a osoby z skupiny PersonGroup. Další informace najdete v tématu Přidání tváří.
Migrace facelistu na LargeFaceList
Rozhraní API pro facelist | Rozhraní API LargeFaceList |
---|---|
Vytvoření | Vytvořit |
Odstranit | Odstranění |
Získat | Získat |
List | List |
Aktualizace | Aktualizace |
- | Trénink |
- | Get Training Status |
Předchozí tabulka je porovnání operací na úrovni seznamu mezi FaceList a LargeFaceList. Jak je vidět, LargeFaceList se dodává s novými operacemi, trénováním a získáním stavu trénování ve srovnání s FaceListem. Trénování LargeFaceList je předpokladem operace FindSimilar. Pro FaceList není potřeba trénování. Následující fragment kódu je pomocná funkce, která čeká na trénování largeFaceListu:
/// <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!");
}
}
}
Dříve typické použití FaceListu s přidanými tvářemi a FindSimilar vypadalo takto:
// 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));
}
}
}
Při migraci na LargeFaceList se stane následující:
// 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));
}
}
}
Jak jsme si ukázali dříve, správa dat a část FindSimilar jsou téměř stejné. Jedinou výjimkou je, že před fungováním funkce FindSimilar musí být v souboru LargeFaceList dokončena nová operace preprocesingu Train.
Krok 2: Trénování návrhů
I když operace Train zrychluje FindSimilar a Identification, čas trénování trpí, zejména při příchodu do velkého rozsahu. Odhadovaný čas trénování v různých škálách je uvedený v následující tabulce.
Měřítko pro tváře nebo osoby | Odhadovaná doba trénování |
---|---|
1000 | 1–2 sekundy |
10,000 | 5–10 sekund |
100 000 | 1–2 min. |
1 000 000 | 10–30 min. |
Pokud chcete lépe využívat funkci ve velkém měřítku, doporučujeme následující strategie.
Krok 2a: Přizpůsobení časového intervalu
Jak je znázorněno, TrainLargeFaceList()
existuje časový interval v milisekundách, který zpožďuje proces kontroly stavu nekonečného trénování. Pro LargeFaceList s více tvářemi s použitím většího intervalu snižuje počet volání a náklady. Přizpůsobit časový interval podle očekávané kapacity LargeFaceList.
Stejná strategie platí také pro LargePersonGroup. Například při trénování LargePersonGroup s 1 milionem osob timeIntervalInMilliseconds
může být 60 000, což je 1 minutový interval.
Krok 2b: Malá vyrovnávací paměť
Osoby nebo tváře ve skupině LargePersonGroup nebo LargeFaceList se dají prohledávat až po vytrénování. V dynamickém scénáři se neustále přidávají nové osoby nebo tváře a musí být okamžitě prohledávatelné, ale trénování může trvat déle, než je žádoucí.
Chcete-li tento problém zmírnit, použijte jako vyrovnávací paměť pouze pro nově přidané položky extra malou skupinu LargePersonGroup nebo LargeFaceList . Trénování této vyrovnávací paměti trvá kratší dobu, protože je menší. Funkce okamžitého vyhledávání v této dočasné vyrovnávací paměti by měla fungovat. Tuto vyrovnávací paměť použijte v kombinaci s trénováním na master LargePersonGroup nebo LargeFaceList spuštěním hlavního trénování v intervalu sparser. Příklady jsou uprostřed noci a denně.
Příklad pracovního postupu:
- Vytvořte master LargePersonGroup nebo LargeFaceList, což je hlavní kolekce. Vytvořte vyrovnávací paměť LargePersonGroup nebo LargeFaceList, což je kolekce vyrovnávací paměti. Kolekce vyrovnávací paměti je určena pouze pro nově přidané osoby nebo tváře.
- Přidejte nové osoby nebo tváře do hlavní kolekce i do kolekce vyrovnávací paměti.
- Vytrénujte pouze kolekci vyrovnávací paměti s krátkým časovým intervalem, aby se zajistilo, že se nově přidané položky projeví.
- Volání Identifikace nebo FindSimilar pro hlavní kolekci i kolekci vyrovnávací paměti. Sloučí výsledky.
- Když se velikost kolekce vyrovnávací paměti zvýší na prahovou hodnotu nebo v době nečinnosti systému, vytvořte novou kolekci vyrovnávací paměti. Aktivujte operaci Train v hlavní kolekci.
- Po dokončení operace Train v hlavní kolekci odstraňte starou kolekci vyrovnávací paměti.
Krok 2c: Samostatné trénování
Pokud je přijatelná relativně dlouhá latence, není nutné aktivovat operaci trénování hned po přidání nových dat. Místo toho je možné operaci trénování rozdělit z hlavní logiky a pravidelně ji aktivovat. Tato strategie je vhodná pro dynamické scénáře s přijatelnou latencí. Dá se použít ve statických scénářích, aby se snížila frekvence trénů .
Předpokládejme, TrainLargePersonGroup
že existuje funkce podobná TrainLargeFaceList
. Typická implementace samostatného trénování pro LargePersonGroup vyvoláním Timer
třídy System.Timers
je:
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();
}
Další informace o správě dat a implementacích souvisejících s identifikací najdete v tématu Přidání tváří.
Shrnutí
V této příručce jste se dozvěděli, jak migrovat existující kód PersonGroup nebo FaceList , nikoli data, do kolekce LargePersonGroup nebo LargeFaceList:
- LargePersonGroup a LargeFaceList fungují podobně jako PersonGroup nebo FaceList s tím rozdílem, že LargeFaceList vyžaduje operaci Train.
- Využijte správnou strategii Trénování k dynamické aktualizaci dat pro rozsáhlé datové sady.
Související obsah
Postupujte podle pokynů a zjistěte, jak přidat tváře do skupiny PersonGroup nebo napsat skript, který provede operaci Identifikace skupiny PersonGroup.