AI時代的網站與手機App建置與開發Part7 - 建立支援貸款授信功能的手機App
· 摘要
如果應用程式本身會佈署到記憶體較為短缺的環境(例如手機, 或是邊緣運算環境)執行, 就會面臨機器學習模型體積大小的限制, 如果機器學習模型體積過大, 無法成功部署到執行環境提供服務, 應用程式就無法內建機器學習服務的功能, 在這種狀況下, 應用程式還是能夠透過部署機器學習模型的Web API專案提供的服務, 叫用機器學習模型提供的功能.
·
處理CORS安全保護問題
部署機器學習模型的Web API專案預設會啟用跨來源資源分享(Cross Origin Resource Sharing – CORS), 禁止和Web API專案不同來源的JavaScript程式呼叫, 如果要解除CORS安全保護, 可以編輯Web API專案根目錄的Program.cs, 於//Configure
app註解下方定義CORS的開放策略:
// Configure app
string MyAllowSpecificOrigins = "AllowOrigin";
builder.Services.AddCors(options
=> {
options.AddPolicy(
name: MyAllowSpecificOrigins,
policy => policy.WithOrigins("*").WithHeaders("*").WithMethods("*"));
});
請注意上述程式碼呼叫WithOrigins函式傳入*當做參數, 表示不限制任何JavaScript程式叫用Web API服務.
定義妥CORS開放策略後, 請於叫用app的Run函式前套用前述定妥的CORS開放策略, 就可以完成解除對JavaScript程式的CORS安全管制.
app.UseCors(MyAllowSpecificOrigins);
app.Run();
· 建立基於MAUI跨平台架構的手機APP專案
請啟動Visual Studio 2022, 執行[檔案 | 新增 | 專案]功能, 選擇建立[.NET MAUI應用程式]型態的專案, 如圖1所示:
圖1: 使用Visual Studio 2022建立[.NET MAUI應用程式]型態的專案的畫面
· 信賴ASP.NET Core HTTPS development certificate
ASP.NET Core Web API專案會使用開發憑証(Development
Certificate)讓Web API能夠支援用戶端使用HTTPS叫用Web API服務的功能, 但是開發憑証並未設定為被信任的憑証, 所以我們要先開啟[命令提示字元]程式, 執行下列的命令, 設定信任ASP.NET Core Web API專案使用的開發憑証:
dotnet dev-certs https --trust
·
建立HttpsClientHandlerService 類別
接下來請為專案加入以下名稱為HttpsClientHandlerService的類別, 負責設定執行在Android模擬器的MAUI手機程式和執行在iOS模擬器的MAUI手機程式信任本機電腦的自我簽署憑証:
public class HttpsClientHandlerService
{
public HttpMessageHandler
GetPlatformMessageHandler()
{
#if ANDROID
var handler = new Xamarin.Android.Net.AndroidMessageHandler();
handler.ServerCertificateCustomValidationCallback = (message,
cert, chain, errors) =>
{
if (cert != null &&
cert.Issuer.Equals("CN=localhost"))
return true;
return errors ==
System.Net.Security.SslPolicyErrors.None;
};
return handler;
#elif IOS
var handler = new
NSUrlSessionHandler
{
TrustOverrideForUrl = IsHttpsLocalhost
};
return handler;
#else
throw new
PlatformNotSupportedException("Only Android and iOS supported.");
#endif
}
#if IOS
public bool
IsHttpsLocalhost(NSUrlSessionHandler sender, string url, Security.SecTrust
trust)
{
if
(url.StartsWith("https://localhost"))
return true;
return false;
}
#endif
}
·
定義描述呼叫部署機器學習模型的Web API服務傳回的執行結果的類別
請參考[AI時代的網站與手機App建置與開發Part5
- 建立支援貸款授信功能的ASP.NET
Core MVC網站]這篇文件提到由ML.NET程式庫產生的MLModel.consumption.cs檔案中的ModelOutput類別, 為專案加入以下的ModelOutput類別, 請注意不可以直接使用ML.NET程式庫生成的ModelOutput類別, 您必須將原先的[ColumnName]全部更換成[JsonPropertyName],
再將@"Features"改成@"features",
將@"PredictedLabel"改成@" predictedLabel",
將@"Score"改成@"score",
編輯妥的ModelOutput類別如下:
public class ModelOutput
{
[JsonPropertyName(@"checking_status")]
public float[] Checking_status { get; set; }
[JsonPropertyName(@"duration")]
public float Duration { get; set; }
[JsonPropertyName(@"credit_history")]
public float[] Credit_history { get; set; }
[JsonPropertyName(@"purpose")]
public float[] Purpose { get; set; }
[JsonPropertyName(@"credit_amount")]
public float Credit_amount { get; set; }
[JsonPropertyName(@"savings_status")]
public float[] Savings_status { get; set; }
[JsonPropertyName(@"employment")]
public float[] Employment { get; set; }
[JsonPropertyName(@"installment_commitment")]
public float Installment_commitment {
get; set; }
[JsonPropertyName(@"personal_status")]
public float[] Personal_status { get; set; }
[JsonPropertyName(@"other_parties")]
public float[] Other_parties { get; set; }
[JsonPropertyName(@"residence_since")]
public float Residence_since { get; set; }
[JsonPropertyName(@"property_magnitude")]
public float[] Property_magnitude { get; set; }
[JsonPropertyName(@"age")]
public float Age { get; set; }
[JsonPropertyName(@"other_payment_plans")]
public float[] Other_payment_plans { get; set; }
[JsonPropertyName(@"housing")]
public float[] Housing { get; set; }
[JsonPropertyName(@"existing_credits")]
public float Existing_credits { get; set; }
[JsonPropertyName(@"job")]
public float[] Job { get; set; }
[JsonPropertyName(@"num_dependents")]
public float Num_dependents { get; set; }
[JsonPropertyName(@"own_telephone")]
public float[] Own_telephone { get; set; }
[JsonPropertyName(@"foreign_worker")]
public float Foreign_worker { get; set; }
[JsonPropertyName(@"class")]
public uint Class { get; set; }
[JsonPropertyName(@"features")]
public float[] Features { get; set; }
[JsonPropertyName(@"predictedLabel")]
public string PredictedLabel { get; set; }
[JsonPropertyName(@"score")]
public float[] Score { get; set; }
}
編輯MAUI手機App專案根目錄下的MainPage.xaml檔案, 將<ScrollView>的內容編輯成以下的樣子, 負責定義貸款申請表單使用者介面:
<ScrollView>
<VerticalStackLayout Padding="30,0"Spacing="25">
<Label Text="Checking_status:"/>
<Entry x:Name="entChecking_status" Text="0<=X<200"></Entry>
<Label Text="Duration:"/>
<Entry x:Name="entDuration" Text="48"></Entry>
<Label Text="Credit_history:"/>
<Entry x:Name="entCredit_history" Text="existing"></Entry>
<Label Text="Purpose:"/>
<Entry x:Name="entPurpose" Text="radio/tv"></Entry>
<Label Text="Credit_amount:"/>
<Entry x:Name="entCredit_amount" Text="5951"></Entry>
<Label Text="Savings_status:"/>
<Entry x:Name="entSavings_status" Text="0<100"></Entry>
<Label Text="Employment:"/>
<Entry x:Name="entEmployment" Text="10<=X0<4"></Entry>
<Label Text="Installment_commitment:"/>
<Entry x:Name="entInstallment_commitment" Text="2"></Entry>
<Label Text="Personal_status:"/>
<Entry x:Name="entPersonal_status" Text="female
div/dep/mar"></Entry>
<Label Text="Other_parties:"/>
<Entry x:Name="entOther_parties" Text="none"></Entry>
<Label Text="Residence_since:"/>
<Entry x:Name="entResidence_since" Text="2"></Entry>
<Label Text="Property_magnitude:"/>
<Entry x:Name="entProperty_magnitude" Text="real
estate"></Entry>
<Label Text="Age:"/>
<Entry x:Name="entAge" Text="22"></Entry>
<Label Text="Other_payment_plans:"/>
<Entry x:Name="entOther_payment_plans" Text="none"></Entry>
<Label Text="Housing:"/>
<Entry x:Name="entHousing" Text="own"></Entry>
<Label Text="Existing_credits:"/>
<Entry x:Name="entExisting_credits" Text="1"></Entry>
<Label Text="Job:"/>
<Entry x:Name="entJob" Text="skilled"></Entry>
<Label Text="Num_dependents:"/>
<Entry x:Name="entNum_dependents" Text="1"></Entry>
<Label Text="Own_telephone:"/>
<Entry x:Name="entOwn_telephone" Text="none"></Entry>
<Label Text="Foreign_worker:"/>
<CheckBox x:Name="cbForeign_worker" IsChecked="False"></CheckBox>
<Button x:Name="BtnLoan" Text="申請" Clicked="OnLoanClicked"
HorizontalOptions="Fill" />
</VerticalStackLayout>
</ScrollView>
·
處理手機App使用者按下貸款申請表單下方的[申請]按鍵的事件
請為MainPage.xaml.cs類別加入以下的OnLoanClicked函式, 負責發送HTTP呼叫至Web API提供的機器學習服務(請注意在Android模擬器執行的手機程式必須使用10.0.2.2 IP位址呼叫佈署在本機電腦的Web API服務), 傳入貸款申請的相關資料, 並顯示貸款申請的結果:
private async void OnLoanClicked(object sender, EventArgs e)
{
//請注意下列的53963為佈署在本機電腦的Web
API服務使用的連接埠
string BaseAddress =
DeviceInfo.Platform == DevicePlatform.Android
? "https://10.0.2.2:53963" : "https://localhost:53963";
//叫用佈署在本機電腦的Web
API服務時請利用HttpsClientHandlerService建立HttpClient類別的物件
#if DEBUG
HttpsClientHandlerService handler = new HttpsClientHandlerService();
HttpClient Client = new
HttpClient(handler.GetPlatformMessageHandler());
#else
HttpClient Client = new
HttpClient();
#endif
object data = new //建立描述貸執申請表單內容的變數並填入使用者填寫的貸款申請資料
{
Checking_status =
entChecking_status.Text,
Duration =
entDuration.Text,
Credit_history =
entCredit_history.Text,
Purpose =
entPurpose.Text,
Credit_amount =
entCredit_amount.Text,
Savings_status =
entSavings_status.Text,
Employment =
entEmployment.Text,
Installment_commitment= entInstallment_commitment.Text,
Personal_status =
entPersonal_status.Text,
Other_parties =
entOther_parties.Text,
Residence_since =
entResidence_since.Text,
Property_magnitude =
entProperty_magnitude.Text,
Age = entAge.Text,
Other_payment_plans
= entOther_payment_plans.Text,
Housing =
entHousing.Text,
Existing_credits =
entExisting_credits.Text,
Job = entJob.Text,
Num_dependents =
entNum_dependents.Text,
Own_telephone =
entOwn_telephone.Text,
Foreign_worker =
cbForeign_worker.IsChecked,
};
string Uri = $"{BaseAddress}/predict"; //欲呼叫的Web
API的端點
string strContent =
JsonSerializer.Serialize(data);
var content = new
StringContent(strContent, Encoding.UTF8, "application/json");
HttpResponseMessage
Response = await Client.PostAsync(Uri,
content);//發送呼叫
Response.EnsureSuccessStatusCode();
string Json = await
Response.Content.ReadAsStringAsync(); //讀取呼叫的結果
var Result =
JsonSerializer.Deserialize<ModelOutput>(Json);
string predictedLabel =
Result.PredictedLabel; //取得貸款申請審核結果
float score =
Result.Score.Max(); //取得信心指數
await DisplayAlert( //顯示貸款申請審核結果
"信用等級", $"{predictedLabel}, 信心指數:${score * 100:n2}%", "關閉");
}
·
執行手機App並送出貸款申請表單
請於Visual
Studio開發工具中使用F5功能鍵以DEBUG模式執行手機App專案, 因為我們的程式會於DEBUG模式利用HttpsClientHandlerService類別建立呼叫位於本機電腦的Web
API服務的HttpClient類別物件, 請注意手機App欲呼叫的Web API服務必須預先啟動, 叫用Web API服務的功能才會成功. 圖2所示即為手機App呼叫佈署機器學習模型的Web API服務的畫面:
圖2: 使用手機App提交貸款申請表單的畫面


留言
張貼留言