Azure ML Studio modelini C# ile online kullanmak

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ı:

file

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.

file

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.

file

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 file 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" file yazan arkası mavi olmayan kısayola bastığımızda bizden girdileri belirtmemizi isteyecek:
file

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:
file

Buna bağlı "Edit Meta Data" kutucuğu da haliyle gereksiz. Onu da çıkartıyorum. Tuvalin son hali aşağıdaki gibi oluyor.
file

Meta verimizi güncelledikten ve gereksiz kutucukları temizledikten sonra servisi yeniden oluşturup, publish edince test sayfası aşağıdaki gibi olacak.

file

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.
file

Açılacak sayfada bizim için yazılmış C# kodunu göreceksiniz.
file

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 Alanve 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.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir