Azure ML'e giriş yazısını yazdıktan sonra doğrudan algoritmalara dalış yaptım. Giriş konuları eksik kalmış oldu. Algoritmalara kısa bir ara verip temel konulara değineceğim. Bu yazıda Azure ML studio üzerinde yaptığmız modeli nasıl bir web servis haline getirip C# projemiz içinden çağırabileceğimizi anlatacağım. C# projesi diye genelliyorum çünkü bu herhangi bir proje türü olabilir Winforms, WPF, Asp.net, Xamarin hiç fark etmez. Tabii işin odağını karıştırmamak adına ben bunu Console projesi üzerinden yapacağım. Aslına bakarsanız tüm işi Azure ML Studio yapıyor olacak. Kodu yazmak dahil.
Bir önceki yazıda bir doğrusal regresyon (doğrusal bağlanım) örneği yapmıştık. Örneğin amacı yüzey alanı ve oda sayısı verilen bir evin fiyatını tahmin etmek idi. Aynı deneyi tekrar açalım, kendisinin tuval üzerinde görünümü aşağıdaki gibi olmalı:
Web servisi oluşturmak için "Set Up Web Service" düğmesine tıklayıp açılan menüden "Predictive Web Service [Recommended]" seçeneğini seçiyoruz. Sizde bu seçenek pasif durumda olabilir. Bu durumda deneyi kaydedin ve çalıştır düğmesine basın. Düğmenin aktif olduğunu göreceksiniz. Hâlâ pasif durumda ise arada hata veren bir kutucuk veya eksik bir kutucuk olmadığından emin olun.
Yorucu tıklama işlemimizin ardından Azure ML Studio bizi kısa bir süre bekletecek ve deneyimiz için ekranda "predictive experiment" adında yeni bir sekme açılacak. Bu sekmenin de kendine has kutucukları var. Bunlar ile Web Servisimizin nasıl çalışacağını yönetiyor olacağız. Yine modeli oluşturduğumuz sekmedeki model buraya ayrı bir kutucuk olarak gelmekte.
Aslında yapmamız gereken bir kaç iş daha var ama onları yapmadığımızda başımıza neler geleceğini göstermek adına bu sefer alttaki menüden düğmesine basıyoruz. Bizim için otomatik olarak bir endpoint oluşturulacak ve doğru çalışıp çalışmadığını görebileceğiz.
Açılan sayfada "TEST" yazan arkası mavi olmayan kısayola bastığımızda bizden girdileri belirtmemizi isteyecek:
Burada "col1,col2,col3" sırasıyla "alan, oda sayısı ve fiyat" anlamına geliyor. Fiyat için bir şey doldurmamıza gerek yok kendisi zaten onu tahmin edecek. Güzel de tahmin etti. Ama girdilerin isimleri anlamsız. Ve servisi çağıranın fiyat bilgisini boş bile olsa göndermesinin bir anlamı yok.
Girdilerin ne olması gerektiğini eğitim verimizden öğreniyor. Web servis için aslında eğitim verisine ihtiyaç yok. Tek amacı input için gereken verinin nasıl olduğuna karar vermek. Eğitim verimizde başlık satırları yoktu. Onları ekleyip, veri ile ilgili satırları siliyoruz. Sorgu sırasında da "Fiyat" kolonu gerekmeyeceği için onu da yok ediyorum. Bir satır da öylesine veri giriyorum ki derleme başarı ile tamamlansın. Neticede kutucuk aşağıdaki hale geliyor:
Buna bağlı "Edit Meta Data" kutucuğu da haliyle gereksiz. Onu da çıkartıyorum. Tuvalin son hali aşağıdaki gibi oluyor.
Meta verimizi güncelledikten ve gereksiz kutucukları temizledikten sonra servisi yeniden oluşturup, publish edince test sayfası aşağıdaki gibi olacak.
Bizim tek bir input ve outputumuz var. Dilerseniz farklı modellerin sonuçlarını aynı input veya farklı inputlarla ekleyebilirsiniz. Bizim için bukadarı yeterli. Sırada C# kodunu yazmak kaldı. Ya da kopyalamak mı deseydim? Bir önceki ekrana dönüp ve "Use Endpoint" kısayolundan ilerleyelim.
Açılacak sayfada bizim için yazılmış C# kodunu göreceksiniz.
Kopyala-yapıştır yeteneklerimizi kullanarak, kendi C# projemize InvokeRequestResponseService
metodunu ve gerekli using
ifadelerini aktarıyoruz.
Kod hazır olmasına hazır ama apiKey
kısmı için yine yeteneklerimizi kullanmamız gerekiyor. Peşinden eğer .net core kullanıyorsanız HttpClient nesnesi için PostAsJsonAsync metodunda sıkıntı olduğunu göreceksiniz. Sizde bu kısım patlamıyorsa aynen devam. Bende patlıyor bu sebeple bir JSON serileştirici ihtiyacım var. Bu örnekte en bilindik olanı seçiyorum ve JSON.net'i kullanıyorum. İlgili NuGet paketlerini yükleyip mağlum satırı aşağıdaki hale çeviriyorum. İhtiyaç halinde sizde böyle yapabilirsiniz.
HttpResponseMessage response = await client.PostAsync("", new StringContent(JsonConvert.SerializeObject(scoreRequest), System.Text.Encoding.UTF8, mediaType: "application/json"));
Koda devam ediyorum Microsoft'un hazır sunduğu InvokeRequestResponseService
metodu iyi hoş ama değerleri parametre olarak almıyor. Metodun içine gömüp geçmişler. Bu sebeple Alan
ve Oda
argümanlarımı açıyorum.
public static async Task InvokeRequestResponseService(int alan, int oda)
Method geriye tahmin değerini döndürmek yerine doğrudan ekrana basıyor bunu da duruma göre düzenleyebilirsiniz. Bende son hali "apiKey" olmaksızın şöyle:
async void Main()
{
await InvokeRequestResponseService(1604,3);
}
static async Task InvokeRequestResponseService(int alan, int oda)
{
using (var client = new HttpClient())
{
var scoreRequest = new
{
Inputs = new Dictionary<string, List<Dictionary<string, string>>>() {
{
"input1",
new List<Dictionary<string, string>>(){new Dictionary<string, string>(){
{
"Alan", alan.ToString()
},
{
"Oda", oda.ToString()
},
}
}
},
},
GlobalParameters = new Dictionary<string, string>()
{
}
};
const string apiKey = "";
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
client.BaseAddress = new Uri("https://ussouthcentral.services.azureml.net/workspaces/03b43cf8daf542f68a9d23c9a971a4d8/services/e7b22f49c6454629866cbec6d48233b8/execute?api-version=2.0&format=swagger");
HttpResponseMessage response = await client.PostAsync("", new StringContent(JsonConvert.SerializeObject(scoreRequest), System.Text.Encoding.UTF8, mediaType: "application/json"));
if (response.IsSuccessStatusCode)
{
string result = await response.Content.ReadAsStringAsync();
Console.WriteLine("Result: {0}", result);
}
else
{
Console.WriteLine(string.Format("The request failed with status code: {0}", response.StatusCode));
Console.WriteLine(response.Headers.ToString());
string responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseContent);
}
}
}
Kullanımda yine 1604 ve 3 değerlerini seçiyorum, çalıştırdığımızda aşağıdaki gibi bir dönüş almalıyız.
Result: {"Results":{"output1":[{"Alan":"1604","Oda":"3","Scored Labels":"289210.090534847"}]}}
Bu kadar basit.
Yeni yazılarda görüşmek üzere.