ChatGPT

2023/3 ChatGPTがとても元気ですね。いろいろな質問に答えてくれますが、時に適当(間違った(^^;)な回答をしてくれることもあるようです。とはいいつつ、プログラムを自動生成してくれたりしてとても便利です。ここではいくつかの実験をしてみます。

Arduinoプログラミング

Q. arduinoでledを2つ交互に点滅するプログラム 

A. 以下は、Arduinoで2つのLEDを交互に点滅させるプログラムの例です。LEDの接続ピンは、自分が使用しているArduinoボードに応じて変更してください。 

int ledPin1 = 2; // LED1の接続ピン

int ledPin2 = 3; // LED2の接続ピン

int delayTime = 500; // 点滅間隔(ミリ秒)


void setup() {

  pinMode(ledPin1, OUTPUT);

  pinMode(ledPin2, OUTPUT);

}


void loop() {

  digitalWrite(ledPin1, HIGH); // LED1を点灯

  digitalWrite(ledPin2, LOW); // LED2を消灯

  delay(delayTime); // 点灯時間待機

  

  digitalWrite(ledPin1, LOW); // LED1を消灯

  digitalWrite(ledPin2, HIGH); // LED2を点灯

  delay(delayTime); // 点灯時間待機

}

このプログラムでは、setup()関数でLEDピンを出力に設定し、loop()関数で2つのLEDを交互に点滅させています。digitalWrite()関数を使用して、LEDの状態をHIGHまたはLOWに設定し、delay()関数を使用して点灯時間を待機しています。 

// 74HC595 ピン定義

const int latchPin = 8; // ラッチピン

const int clockPin = 12; // クロックピン

const int dataPin = 11; // データピン


void setup() {

  pinMode(latchPin, OUTPUT);

  pinMode(clockPin, OUTPUT);

  pinMode(dataPin, OUTPUT);

}


void loop() {

  for (int i = 0; i < 10; i++) {

    shiftOut(dataPin, clockPin, MSBFIRST, 1 << i); // 1ビットだけシフトして、LEDを点灯

    digitalWrite(latchPin, HIGH); // ラッチピンをHIGHに設定して、シフトレジスタの出力を更新

    digitalWrite(latchPin, LOW); // ラッチピンをLOWに設定して、シフトレジスタの出力を固定

    delay(100); // 100ミリ秒待機

    shiftOut(dataPin, clockPin, MSBFIRST, 0); // 0ビットだけシフトして、LEDを消灯

    digitalWrite(latchPin, HIGH); // ラッチピンをHIGHに設定して、シフトレジスタの出力を更新

    digitalWrite(latchPin, LOW); // ラッチピンをLOWに設定して、シフトレジスタの出力を固定

  }

}

回路図も描いてもらおうと思いましたが、それは無理のようでした。

その代わりに必要な部品と接続法を聞いてみました。

すっごいですね。どんどんプログラムが作れそうです(^^V

PyTorchプログラミング

ではPyTorchのプログラムに挑戦してみます。

以下、画像では全体を示せませんでしたので、テキストとさせていただきます。

import torch

import torch.nn as nn

import torchvision.datasets as dsets

import torchvision.transforms as transforms


# データの読み込み

train_dataset = dsets.MNIST(root='./data', train=True, transform=transforms.ToTensor(), download=True)

test_dataset = dsets.MNIST(root='./data', train=False, transform=transforms.ToTensor())


# ハイパーパラメータの設定

input_size = 784  # 入力層のノード数

hidden_size = 500  # 隠れ層のノード数

num_classes = 10  # 出力層のノード数

num_epochs = 5  # エポック数

batch_size = 100  # バッチサイズ

learning_rate = 0.001  # 学習率


# データローダーの作成

train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)

test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)


# ニューラルネットワークの定義

class NeuralNet(nn.Module):

    def __init__(self, input_size, hidden_size, num_classes):

        super(NeuralNet, self).__init__()

        self.fc1 = nn.Linear(input_size, hidden_size)

        self.relu = nn.ReLU()

        self.fc2 = nn.Linear(hidden_size, num_classes)

    

    def forward(self, x):

        out = self.fc1(x)

        out = self.relu(out)

        out = self.fc2(out)

        return out


model = NeuralNet(input_size, hidden_size, num_classes)


# 損失関数と最適化アルゴリズムの定義

criterion = nn.CrossEntropyLoss()

optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)


# 学習

total_step = len(train_loader)

for epoch in range(num_epochs):

    for i, (images, labels) in enumerate(train_loader):

        # 入力データの整形

        images = images.reshape(-1, 28*28)

        

        # 順伝播と損失の計算

        outputs = model(images)

        loss = criterion(outputs, labels)

        

        # 逆伝播とパラメータの更新

        optimizer.zero_grad()

        loss.backward()

        optimizer.step()

        

        # ログ出力

        if (i+1) % 100 == 0:

            print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, i+1, total_step, loss.item()))


# テスト

with torch.no_grad():

    correct = 0

    total = 0

    for images, labels in test_loader:

        # 入力データの整形

        images = images.reshape(-1, 28*28)

        

        # 順伝播と予測の計算

        outputs = model(images)

        _, predicted = torch.max(outputs.data, 1)

        

        # 正解数のカウント

あれ、途中までで止まっていますね。ChromeのExtensionでChatGPT for Googleというものがあり、これを導入すると最後まで書いてくれます(その後の検証でこちらも最後までは書いてくれませんでした(^^; またこのExtensionを使うとすべてのGoogle検索がChatGPT検索も行うので、ChatGPTのサイトで確認すると検索結果がいっぱいになっています。このままで大丈夫なのか??)。その結果を示します。

Google検索(あるいはアドレスバー)で「pytorchで2層のニューラルネットを作り、mnistの数字判別できるようにしてください。」と入力すると、画面右側にChatGPTの回答が出てきます。ここは途中で切られずに最後まで書いてくれるようです。

ということで、再度やってみます。

Google検索で「pytorchで2層のニューラルネットを作り、mnistの数字判別できるようにしてください。」と検索します。すると、

以下のコードは、PyTorchを使用して2層のニューラルネットワークを定義し、MNISTデータセットを使用して数字分類を行う方法の例です。

import torch

import torchvision

import torchvision.transforms as transforms


# データセットの読み込みと前処理

transform = transforms.Compose(

    [transforms.ToTensor(),

     transforms.Normalize((0.5,), (0.5,))])


trainset = torchvision.datasets.MNIST(root='./data', train=True,

                                        download=True, transform=transform)

trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,

                                          shuffle=True)


testset = torchvision.datasets.MNIST(root='./data', train=False,

                                       download=True, transform=transform)

testloader = torch.utils.data.DataLoader(testset, batch_size=64,

                                         shuffle=False)


# ネットワークの定義

class Net(torch.nn.Module):

    def __init__(self):

        super(Net, self).__init__()

        self.fc1 = torch.nn.Linear(28*28, 128)

        self.fc2 = torch.nn.Linear(128, 10)


    def forward(self, x):

        x = x.view(-1, 28*28)

        x = torch.relu(self.fc1(x))

        x = self.fc2(x)

        return x


net = Net()


# 損失関数と最適化手法の定義

criterion = torch.nn.CrossEntropyLoss()

optimizer = torch.optim.SGD(net.parameters(), lr=0.001, momentum=0.9)


# 学習

for epoch in range(10):  # データセットを複数回使用するためのループ

    running_loss = 0.0

    for i, data in enumerate(trainloader, 0):

        # 入力と正解ラベルの取得

        inputs, labels = data


        # 勾配を初期化

        optimizer.zero_grad()


        # 順伝播と逆伝播

        outputs = net(inputs)

        loss = criterion(outputs, labels)

        loss.backward()


        # パラメータの更新

        optimizer.step()


        # 統計情報の表示

        running_loss += loss.item()

        if i % 100 == 99:    # 100ミニバッチごとに表示

            print('[%d, %5d] loss: %.3f' %

                  (epoch + 1, i + 1, running_loss / 100))

            running_loss = 0.0


print('Finished Training')


# テストデータでの精度の計算

correct = 0

total = 0

with torch.no_grad():

    for data in testloader:

        inputs, labels = data

        outputs = net(inputs)

        _, predicted = torch.max(outputs.data, 1)

        total += labels.size(0)

        correct += (predicted == labels).sum().item()


print('Accuracy of the network on the 10000 test images: %d %%' % (

    100 * correct / total))

このコードでは、`Net`クラスを定義して、`torch.nn.Linear`を使用して2つの線形層を作成しています。最初の層は入力画像のピクセル


ん?? こちらも途中で切れていますね。やはり無料ではここまででしたか。とはいえ、このままコピペしてPython環境で走らせると(PyTorchなどの環境設定は必要ですが)そのまま走ります。すごいですねえ!

その他

Q. 2次方程式の解の公式は? 

A. 

2次方程式ax^2 + bx + c = 0の解は、以下の公式を用いて求めることができます。

x = (-b ± sqrt(b^2 - 4ac)) / 2a

ここで、±はプラスとマイナスの両方の解を表します。また、sqrtは平方根を表し、b^2 - 4acの部分は判別式と呼ばれます。判別式が正の場合は2つの実数解があり、判別式が0の場合は重解があり、判別式が負の場合は2つの虚数解があります。

Q. 2関節のシリアルリンクマニピュレータの逆運動学を教えてください。 

A. 

2関節のシリアルリンクマニピュレータの逆運動学は、与えられたエンドエフェクタの位置と姿勢から、各関節の角度を求める問題です。以下のように解くことができます。

まず、与えられたエンドエフェクタの位置を(x, y)、関節1とエンドエフェクタの距離をl1、関節2とエンドエフェクタの距離をl2とします。

まず、関節2の角度θ2を求めます。関節2の角度は、エンドエフェクタがx軸に対してどの角度であるかに依存します。以下の式を使用してθ2を計算できます。

θ2 = acos((x^2 + y^2 - l1^2 - l2^2) / (2 * l1 * l2))

次に、関節1の角度θ1を求めます。θ1は、関節2の角度に依存します。以下の式を使用してθ1を計算できます。

θ1 = atan2(y, x) - atan2(l2 * sin(θ2), l1 + l2 * cos(θ2))

これで、与えられたエンドエフェクタの位置から、各関節の角度を求めることができます。

注意点として、この逆運動学解は、2関節のマニピュレータに対して一意に解が存在する場合にのみ有効です。特に、マニピュレータのリーチ能力が限られている場合、またはエンドエフェクタの位置が不可能な場合、解が存在しない可能性があります。

うーーん、すごいですねえ。