opencv は、Java、C++、Python のライブラリ依存関係を持つオープン ソース グラフィックス ライブラリであり、モデル トレーニングを十分にサポートしていませんが、予測のために他のフレームワークでトレーニングされたモデルを読み込むことができます。
これは線形回帰の最も単純な例です。深層学習フレームワーク pytorch を使用してモデルをトレーニングし、最後にモデルを onnx 形式で保存します。最後に、opencv-python ライブラリが負荷予測に使用されます。
ここで用意した線形回帰モデルのデータは以下のとおりです。
x_data | y_data |
1 | 2 |
2 | 4 |
3 | 6 |
4 | ? |
8 | ? |
10 | ? |
15 | ? |
直感的には、これは実際には y = 2x の一次方程式です。しかし、機械学習では、最終的な係数、w と b の値を取得するには、継続的な反復が必要です。
この記事で使用されている Python ライブラリのバージョン:
- トーチ:1.13.0
- opencv-python: 4.5.5
- ナンピー1.24.2
- パイソン:3.10
コードを見せてください:
import torch
x_data = torch.Tensor([[1.0], [2.0], [3.0]])
y_data = torch.Tensor([[2.0], [4.0], [6.0]])
class LinearModel(torch.nn.Module):
def __init__(self):
super(LinearModel, self).__init__()
self.linear = torch.nn.Linear(1, 1)
def forward(self, x):
return self.linear(x)
model = LinearModel()
criterion = torch.nn.MSELoss(reduction='sum')
optimizer = torch.optim.SGD(model.parameters(), lr=0.02)
for epoch in range(1000):
y_pred = model(x_data)
loss = criterion(y_pred, y_data)
if epoch % 100 == 0:
print(epoch + 1, loss)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print('w = {}'.format(model.linear.weight.item()))
print('b = {}'.format(model.linear.bias.item()))
x_test = torch.Tensor([[4.0]])
y_test = model(x_test)
print('y_pred(4.0) = ', y_test.data)
x_test = torch.Tensor([[8.0]])
y_test = model(x_test)
print('y_pred(8.0) = ', y_test.data)
x_test = torch.Tensor([[10.0]])
y_test = model(x_test)
print('y_pred(10.0) = ', y_test.data)
x_test = torch.Tensor([[15.0]])
y_test = model(x_test)
print('y_pred(15.0) = ', y_test.data)
model.eval()
dummy_input = torch.randn(1, 1)
input_name = ["input"]
output_name = ["output"]
onnx_name = "test.onnx"
torch.onnx.export(
model,
dummy_input,
onnx_name,
verbose=True,
input_names=input_name,
output_names=output_name
)
次のように実行して情報を出力します。
ここで注目するのは、線形回帰係数、w = 1.99、b = 1.31 です。ここでの w は実際には 2 に非常に近いです。結局のところ、これはコンピュータによって計算されます。勾配降下法アルゴリズムについてはここでは明示的には述べられていませんが、実際にはトレーニング部分では実際に勾配降下法が使用されています。
for epoch in range(1000):
y_pred = model(x_data)
loss = criterion(y_pred, y_data)
if epoch % 100 == 0:
print(epoch + 1, loss)
optimizer.zero_grad()
loss.backward()
optimizer.step()
最後に、この回帰係数による予測は期待と一致しています。
このアルゴリズムは最終的に、ローカル プロジェクト パスの下の test.onnx ファイルにモデルを保存します。
//
上記はモデルの準備ができたものとみなされます。次に、opencv-python を介してモデルをロードし、予測します。
from cv2 import dnn
import numpy as np
net = dnn.readNetFromONNX("test.onnx")
matblob = np.full((1, 1), 1024, dtype=np.int32)
net.setInput(matblob)
print('input = {}'.format(matblob))
output = net.forward()
print('output = {}'.format(output))
ここで, matblob は実際には Mat ですが, opencv-python では numpy を通じて作成できます. ここインターネットでは, matblob オブジェクトは画像を読み取ることによって生成されます. 個人的には、ここで非常に明確であると感じています, つまり、必要があります数値 1024 を指定するには、np.full() を通じて列、行、タイプ、値を設定し、この入力 Mat オブジェクトを正常に作成します。
このコードを実行すると、2048 が得られると予想されますが、実際の結果は次のようになります。
実際、これは 2048 年に非常に近いです。これは Python コードの結果です。opencv-c++ を使用してコーディングする場合、コードは基本的に似ています。C++ は試しませんでしたが、主にこのモデルは Python コードで実装および生成されており、opencv には Python の依存関係ライブラリがあるため、Python で直接実装することを考えました。opencv-c++ の実装を勉強する必要はありません。