Créez un modèle de régression linéaire en python et utilisez ce modèle pour ** déduire ** sur Android. (Il n'est pas formé sur Android.)
Ce code est publié sur github, veuillez donc vous y référer le cas échéant. (URL publiée en bas)
Celui que je fais cette fois ↓
・ Utilisez ** PyTorch Mobile **
Tout d'abord, créez un modèle linéaire à exécuter sur Android. Si vous ne disposez pas d'un environnement python et souhaitez lire uniquement les utilisateurs d'Android, passez à l'en-tête ** Inférence avec Android ** et téléchargez le modèle terminé.
Le code affiché cette fois est celui qui a été exécuté sur le notebook jupyter.
Pour l'ensemble de données utilisé cette fois, essayez d'utiliser Qualité du vin rouge répertorié dans kaggle.
C'est comme prédire ** 10 niveaux de qualité du vin ** à partir de données sur les ingrédients du vin telles que l'acidité, le pH et la fréquence.
Cette fois, je veux juste déplacer le modèle linéaire sur Android, donc j'utiliserai une régression multiple linéaire simple pour voir la qualité en 10 étapes comme une valeur continue et l'ajuster au modèle linéaire. Il y a 11 colonnes, mais il n'y a pas de régularisation L1 particulière. (Hmm, la précision semble s'aggraver ...)
Affichez les données, recherchez les zones manquantes et organisez les données.
Importer des données téléchargées depuis 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')
Pour le moment, tracez la corrélation, vérifiez les défauts.
sns.pairplot(wineQualityData)
#Vérification des données manquantes
wineQualityData.isnull().sum()
D'autant que cela peut être une valeur manquante, nous créerons ensuite un chargeur de données
#Entrée et étiquette correcte
X = wineQualityData.drop(['quality'], 1)
y = wineQualityData['quality']
#8:Diviser par 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:Diviser par 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)
#Création du chargeur de données
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)
Il est facile d'avoir une méthode dans pytorch qui facilite la création d'un chargeur de données. Je crée des données de test cette fois, mais je ne les utiliserai pas cette fois.
Ensuite, nous allons créer un modèle linéaire.
from torch import nn, optim
#modèle
model = nn.Linear(in_features = 11, out_features=1, bias=True)
#Taux d'apprentissage
lr = 0.01
#Erreur carrée
loss_fn=nn.MSELoss()
#Journal des fonctions de perte
losses_train= []
#Fonction d'optimisation
optimizer = optim.Adam(model.parameters(), lr=lr)
Former le modèle créé
from tqdm import tqdm
for epoch in tqdm(range(100)):
print("epoch:", epoch)
for x,y in train_loader:
#Mettre à zéro le dégradé précédent
optimizer.zero_grad()
#Prévoir
y_pred = model(x)
#Calculer la différenciation par perte MSE et w
loss = loss_fn(y_pred, y)
if(epoch != 0): #Terminer lorsque l'erreur devient petite
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 de la fonction de perte
plt.plot(losses_train)
Il semble qu'il converge pour le moment.
Essayez un petit modèle
for i in range(len(X_test)):
print("Résultat d'inférence:",model(X_test[i]).data, "Étiquette de réponse correcte:", y_test[i].data)
Hmm? Ça ne va pas du tout. C'est juste une régression multiple linéaire, mais je me demande si ça ne va pas si bien. En regardant à nouveau les données, 56% de la qualité était de 5. En d'autres termes, je me demande si elle a presque convergé vers une valeur de 5 pour réduire la perte. En premier lieu, était-il difficile de considérer ces données comme une étiquette de valeur continue et d'effectuer une régression multiple linéaire? Il aurait peut-être été préférable de le faire par classification.
Cependant, cette fois ce n'est pas l'essentiel de demander la précision du modèle, donc pour le moment, disons que le modèle est terminé.
Si vous savez que le code est mauvais ici en raison de la mauvaise précision cette fois, veuillez nous le faire savoir dans les commentaires.
Enregistrez le modèle pour mettre le modèle sur Android
import torchvision
model.eval()
#Taille du tenseur d'entrée
example = torch.rand(1,11)
traced_script_module = torch.jit.trace(model, example)
traced_script_module.save("wineModel.pt")
S'il peut être exécuté avec succès, un fichier pt doit être généré dans le même dossier.
Si vous l'avez ignoré, veuillez télécharger le modèle entraîné depuis github.
De là, nous utiliserons Android Studio.
À partir de mars 2020
build.gradle
dependencies {
implementation 'org.pytorch:pytorch_android:1.4.0'
implementation 'org.pytorch:pytorch_android_torchvision:1.4.0'
}
Placez le modèle entraîné (wineModel.pt) que vous avez téléchargé ou créé précédemment dans Android Studio.
Tout d'abord, ** créez un dossier d'actifs ** (vous pouvez le créer en cliquant avec le bouton droit sur le dossier res ou un emplacement approprié-> nouveau-> dossier-> dossier d'actifs) Copiez-y le modèle entraîné.
Créez une mise en page qui affiche les résultats de l'inférence. Cependant, je viens d'organiser 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="Prévisions de qualité des vins rouges"
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>
Chargez le modèle, mettez le tenseur et inférez
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Données de test de vin
val inputArray = floatArrayOf(7.1f, 0.46f, 0.2f, 1.9f, 0.077f, 28f, 54f, 0.9956f, 3.37f, 0.64f, 10.4f)
//Génération Tensol:argument(floatArray,Taille Tensol)
val inputTensor = Tensor.fromBlob(inputArray, longArrayOf(1,11))
//Chargement du modèle
val module = Module.load(assetFilePath(this, "wineModel.pt"))
//inférence
val outputTensor = module.forward(IValue.from(inputTensor)).toTensor()
val scores = outputTensor.dataAsFloatArray
//Voir les résultats
result.text ="Valeur prédite: ${scores[0]}"
label.text = "Étiquette de réponse correcte: 6"
}
//Fonction pour obtenir le chemin du dossier d'actifs
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
}
}
}
Achevée! !! Si vous arrivez à ce point et que vous l'exécutez, l'écran d'ouverture devrait apparaître.
Le système d'image est aussi un tutoriel, mais j'ai écrit cet article car il n'y avait pas grand-chose sur la linéarité ordinaire. La précision du modèle n'était pas bonne, mais j'ai pu déplacer le modèle linéaire pour le moment. Essayons de classer cette fois.
Cliquez ici pour ce code code python code du studio android