Create a linear regression model in python and use that model to ** infer ** on android. (It is not trained on android.)
This code is posted on github, so please refer to it as appropriate. (URL posted at the bottom)
The one I make this time ↓
・ Use ** PyTorch Mobile **
First, we will create a linear model to run on android. If you don't have a python environment and want to read only Android users, skip to the heading ** Inference with Android ** and download the completed model.
The code posted this time is the one that was run on the jupyter notebook.
For the dataset used this time, try using Red Wine Quality listed in kaggle.
It feels like predicting ** 10 levels of quality of wine ** from wine component data such as sourness, pH, and frequency.
This time, I just want to move the linear model on android, so I will use a simple linear multiple regression to see the 10-step quality as a continuous value and fit it with the linear model. There are 11 columns, but there is no L1 regularization in particular. (Hmm, the accuracy seems to get worse ...)
View data, check for missing areas, and organize data.
Import data downloaded from kaggle
import torch
from matplotlib import pyplot as plt
import pandas as pd
import seaborn as sns
wineQualityData = pd.read_csv('datas/winequality-red.csv')
For the time being, plot the correlation, check for defects ..
sns.pairplot(wineQualityData)
#Check for missing data
wineQualityData.isnull().sum()
Especially since it may be a missing value, we will create a data loader next
#Input and correct label
X = wineQualityData.drop(['quality'], 1)
y = wineQualityData['quality']
#8:Divide by 2
X_train = torch.tensor(X.values[0:int(len(X)*0.8)], dtype=torch.float32)
X_test = torch.tensor(X.values[int(len(X)*0.8):len(X)], dtype=torch.float32)
#8:Divide by 2
y_train = torch.tensor(y.values[0:int(len(y)*0.8)], dtype=torch.float32)
y_test = torch.tensor(y.values[int(len(y)*0.8):len(y)], dtype=torch.float32)
#Data loader creation
train = torch.utils.data.TensorDataset(X_train, y_train)
train_loader = torch.utils.data.DataLoader(train, batch_size=100, shuffle=True)
test = torch.utils.data.TensorDataset(X_test, y_test)
test_loader = torch.utils.data.DataLoader(test, batch_size=50, shuffle=False)
It's easy to have a method in pytorch that makes it easy to create a data loader. I'm making test data this time, but I won't use it this time.
Next, we will make a linear model.
from torch import nn, optim
#model
model = nn.Linear(in_features = 11, out_features=1, bias=True)
#Learning rate
lr = 0.01
#Square error
loss_fn=nn.MSELoss()
#Loss function log
losses_train= []
#Optimization function
optimizer = optim.Adam(model.parameters(), lr=lr)
Train the created model
from tqdm import tqdm
for epoch in tqdm(range(100)):
print("epoch:", epoch)
for x,y in train_loader:
#Zero the previous gradient
optimizer.zero_grad()
#Forecast
y_pred = model(x)
#Calculate the derivative by MSE loss and w
loss = loss_fn(y_pred, y)
if(epoch != 0): #End when the error becomes small
if abs(losses_train[-1] - loss.item()) < 1e-1:
break
loss.backward()
optimizer.step()
losses_train.append(loss.item())
print("train_loss", loss.item())
Transition of loss function
plt.plot(losses_train)
It seems that it is converging for the time being.
Try a little model
for i in range(len(X_test)):
print("Inference result:",model(X_test[i]).data, "Correct label:", y_test[i].data)
Hmm? It doesn't fit at all. It's just a linear multiple regression, but I wonder if it doesn't fit so well. Looking at the data again, 56% of the quality was 5. In other words, I wonder if it has almost converged to a value of 5 so as to reduce the loss. In the first place, was it difficult to regard such data as a continuous value label and perform linear multiple regression? It might have been better to do it by classification.
However, this time it is not the main thing to ask for the accuracy of the model, so for the time being, let's say that the model is completed.
If you know that the code is bad here because of the poor accuracy this time, please let us know in the comments.
Save the model to put the model on android
import torchvision
model.eval()
#Input tensor size
example = torch.rand(1,11)
traced_script_module = torch.jit.trace(model, example)
traced_script_module.save("wineModel.pt")
If it can be executed successfully, a pt file should be generated in the same folder.
If you skipped it, please download the trained model from github.
From here, we will use Android Studio.
As of March 2020
build.gradle
dependencies {
implementation 'org.pytorch:pytorch_android:1.4.0'
implementation 'org.pytorch:pytorch_android_torchvision:1.4.0'
}
Put the trained model (wineModel.pt) you downloaded or created earlier in Android Studio.
First, create an asset folder ** (you can create it by right-clicking on the res folder or a suitable location-> new-> folder-> asset folder) Copy the trained model there.
Create a layout that displays the inference results. However, I just arranged 3 textViews.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/label" />
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:textSize="30sp"
app:layout_constraintBottom_toTopOf="@+id/result"
app:layout_constraintEnd_toEndOf="@+id/result"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/result"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Red wine quality forecast"
android:textSize="30sp"
app:layout_constraintBottom_toTopOf="@+id/label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Load the model, put the tensor and infer
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Wine test data
val inputArray = floatArrayOf(7.1f, 0.46f, 0.2f, 1.9f, 0.077f, 28f, 54f, 0.9956f, 3.37f, 0.64f, 10.4f)
//Generation of tensor:argument(floatArray,Tensor size)
val inputTensor = Tensor.fromBlob(inputArray, longArrayOf(1,11))
//Model loading
val module = Module.load(assetFilePath(this, "wineModel.pt"))
//inference
val outputTensor = module.forward(IValue.from(inputTensor)).toTensor()
val scores = outputTensor.dataAsFloatArray
//View results
result.text ="Predicted value: ${scores[0]}"
label.text = "Correct label: 6"
}
//Function to get the path from the asset folder
fun assetFilePath(context: Context, assetName: String): String {
val file = File(context.filesDir, assetName)
if (file.exists() && file.length() > 0) {
return file.absolutePath
}
context.assets.open(assetName).use { inputStream ->
FileOutputStream(file).use { outputStream ->
val buffer = ByteArray(4 * 1024)
var read: Int
while (inputStream.read(buffer).also { read = it } != -1) {
outputStream.write(buffer, 0, read)
}
outputStream.flush()
}
return file.absolutePath
}
}
}
Complete! !! If you come to this point and execute it, the opening screen should appear.
The image system is also a tutorial, but I wrote this article because there wasn't much about ordinary linearity. The accuracy of the model was not good, but I was able to move the linear model for the time being. Let's try to classify this time.
Click here for this code python code android studio code
Recommended Posts