戻る

ChatGPTで3D Audio生成

2025/02/12

概要

ChatGPTが日々進化していることを実感する。

コロナ禍の頃JavaScriptを使った3D画像のプログラミングに没頭したことがあった。

最初は3Dオブジェクト(球体や立方体など)を動かすことから始まったが、単純な動きでなく変化をつけるため音楽と同期するようにした。その後、オーディオデータを周波数分解し周波数に合わせて動かすようにした。しかしながら仮想の3D空間でオブジェクトを動かすことは難しく、三角関数を使ったりしてみたが十分に納得するには至っていないと自覚していた。

オーディオデータを周波数分解したまでは良かったが、実際に分解したデータを使ってオブジェクトを動かすと、変化が激しく小刻みに震えるように見えて、とても使えない。

今回同様のことをChatGPTがどこまで出来るかを実験した。

結果、予想はしていたがCahtGPTのコーディングスキルのすばらしさに改めて感心した。

ChatGPTにプロンプト

Javascript でthree.jsを使ったプログラムを作りたい。オーディオデータを周波数分解して変数として3Dオブジェクトを動かしたい

コード

ChatGPTの生成コードにプロンプトを追加し、さらに自分仕様にカストマイズした。

<!DOCTYPE html> <html lang="ja"> <head> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <title>Smooth Audio-Driven Cube with Starfield & Audio Progress Display</title> <style> body { width: 100%; margin: 0; overflow: hidden; background-color: #000; } /* 音楽名 */ #music_title { position: absolute; top: 0px; left: 10px; color: #fff; font-family: Arial, sans-serif; font-size: 16px; z-index: 10; } /* 画面左上にオーディオ進捗表示(seed表示の下) */ #audioProgress { position: absolute; top: 20px; left: 10px; color: #fff; font-family: Arial, sans-serif; font-size: 16px; z-index: 10; } /* オーディオ開始のためのインストラクション */ #instructions { position: absolute; top: 40px; left: 10px; color: #fff; font-family: Arial, sans-serif; font-size: 16px; z-index: 10; } </style> </head> <body> <!-- 音楽名 --> <div id="music_title"></div> <!-- オーディオ進捗表示 --> <div id="audioProgress"></div> <!-- インストラクション --> <div id="instructions">Click anywhere to start audio</div> <!-- canvas define ---> <canvas id="myCanvas"></canvas> <!-- Three.js の読み込み --> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <!-- 3d define ------- --> <script> // canvas size get const canvasElement = document.querySelector("#myCanvas"); const width = window.innerWidth; const height = window.innerHeight; // -------------------- 画像 & 音楽 ------------------------- const image1 = "img/image_fx_1.jpg" const image2 = "img/image_fx_2.jpg" const image3 = "img/image_fx_3.jpg" const image4 = "img/image_fx_4.jpg" const music = "audio/Tchaikovsky-Nutcracker-Pas-de-Deux-Adage.mp3"; const mtitle = "Tchaikovsky : Nutcracker Pas de Deux"; document.getElementById("music_title").textContent = mtitle ; // --------------------------- // Seed & Random Generator Setup // --------------------------- const INITIAL_SEED = 98765; // document.getElementById("seedDisplay").textContent = "Seed: " + INITIAL_SEED; function createSeededRandom(seed) { let state = seed; return function () { state = (state * 1664525 + 1013904223) % 4294967296; return state / 4294967296; }; } const random = createSeededRandom(INITIAL_SEED); // --------------------------- // Three.js Scene Setup // --------------------------- // レンダラーを作成 const renderer = new THREE.WebGLRenderer({ canvas: canvasElement, alpha: true }); const aspectRatio = width / height; renderer.setClearColor(0x000000); renderer.setSize(width, height); renderer.setPixelRatio(window.devicePixelRatio); renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; // シーンを作成 const scene = new THREE.Scene(); // カメラ作成 const camera = new THREE.PerspectiveCamera(75, aspectRatio, 6 , 1000); camera.position.x = 0; camera.position.y = 2; camera.position.z = 13; // --- 地面の作成 --- // 影を受ける平面(地面)を追加しておくと、スポットライトの影がわかりやすくなります。 const planeGeometry = new THREE.PlaneGeometry(100, 100); const planeMaterial = new THREE.MeshPhongMaterial({ color: 0x555555 }); const plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.rotation.x = - Math.PI / 1.7; plane.position.y = - 4; plane.receiveShadow = true; scene.add(plane); // --------------------- 環境光 を作成 ------------------------------- const ambientLight = new THREE.AmbientLight(0x888888); scene.add(ambientLight); // --- Spotlight(スポットライト)の追加 --- // スポットライトは一点を照らす集中光源です。 const spotLight = new THREE.SpotLight(0xcccccc, 1.0); spotLight.position.set( 0 , 15 , 8 ); // ライトの位置 spotLight.angle = Math.PI / 6; // 光が広がる角度 spotLight.penumbra = 0.1 ; // 光のにじみ具合(エッジの柔らかさ) spotLight.decay = 0; // 距離減衰の強さ spotLight.distance = 500; // 光が届く距離 // 影のキャストを有効に spotLight.castShadow = true; // 影の解像度(必要に応じて調整) spotLight.shadow.mapSize.width = width; spotLight.shadow.mapSize.height = height; spotLight.shadow.camera.near = 1.5; spotLight.shadow.camera.far = 1500; scene.add(spotLight); // const spotLightHelper = new THREE.SpotLightHelper(spotLight); // scene.add(spotLightHelper); // --------------------------- // Textured Cube Setup // --------------------------- // Cube の各面は次の順番:[右, 左, 上, 下, 前, 後] const textureLoader = new THREE.TextureLoader(); // cube1 const materials1 = [ new THREE.MeshPhongMaterial({ map: textureLoader.load(image1), side: THREE.DoubleSide }), // Right new THREE.MeshPhongMaterial({ map: textureLoader.load(image1), side: THREE.DoubleSide }), // Left new THREE.MeshPhongMaterial({ transparent: true, opacity: 0 }), // Top (plain color) new THREE.MeshPhongMaterial({ transparent: true, opacity: 0 }), // Bottom (plain color) new THREE.MeshPhongMaterial({ map: textureLoader.load(image2), side: THREE.DoubleSide }), // Front new THREE.MeshPhongMaterial({ map: textureLoader.load(image2), side: THREE.DoubleSide }) // Back ]; const cubeGeometry1 = new THREE.BoxGeometry(2, 1.12, 2); const cube1 = new THREE.Mesh(cubeGeometry1, materials1); cube1.receiveShadow = true; // キューブ上に他の影が乗る(必要に応じて) scene.add(cube1); // --------------------------- // Star field Background Setup // --------------------------- const starCount = 5000; const starGeometry = new THREE.BufferGeometry(); const starPositions = new Float32Array(starCount * 3); for (let i = 0; i < starCount; i++) { starPositions[i * 3] = (random() - 0.5) * 200; starPositions[i * 3 + 1] = (random() - 0.5) * 200; starPositions[i * 3 + 2] = (random() - 0.5) * 200; } starGeometry.setAttribute('position', new THREE.BufferAttribute(starPositions, 3)); const starMaterial = new THREE.PointsMaterial({ color: 0xffff88, size: 0.1 }); const stars = new THREE.Points(starGeometry, starMaterial); scene.add(stars); // -------------------------------- // Load a font and create 3D text once the font is loaded // -------------------------------- // グローバル変数として textMesh を宣言 let textMesh; let radiustext = 2.0; let anggletext = 0; const fontLoader = new THREE.FontLoader(); fontLoader.load( 'https://threejs.org/examples/fonts/helvetiker_regular.typeface.json', function (font) { // Create TextGeometry with your custom text const textGeometry = new THREE.TextGeometry(mtitle, { font: font, size: 0.3, // Size of the text height: 0.1 , // Thickness of the text curveSegments: 6 , // Number of segments on the curves bevelEnabled: true, // Enable bevel (rounded edges) bevelThickness: 0.01, bevelSize: 0.02, bevelOffset: 0, bevelSegments: 1 }); // Create a material that reacts to light (e.g., from a spotlight) const textMaterial = new THREE.MeshPhongMaterial({ color: 0xc0c0c0 }); // Create a Mesh from the geometry and material textMesh = new THREE.Mesh(textGeometry, textMaterial); // Position the text in the scene (adjust as needed) textGeometry.center(); textMesh.castShadow = true; // 影を落とす textMesh.receiveShadow = true; // 上に他の影が乗る(必要に応じて) // Add the text Mesh to your scene scene.add(textMesh); textMesh.position.x = - 5; textMesh.position.y = 0 ; textMesh.rotation.x = - 0.2; } ); // --------------------------- // Audio Setup (Web Audio API) // --------------------------- let audioContext, analyser, frequencyData; const audio = new Audio(); // ----------- 音楽名 ------------------ audio.src = music; audio.crossOrigin = "anonymous"; // オーディオの進捗表示更新用の関数(秒を mm:ss に変換) function formatTime(time) { const minutes = Math.floor(time / 60); const seconds = Math.floor(time % 60); return minutes + ":" + (seconds < 10 ? "0" : "") + seconds; } document.body.addEventListener('click', () => { if (!audioContext) { audioContext = new (window.AudioContext || window.webkitAudioContext)(); analyser = audioContext.createAnalyser(); analyser.fftSize = 256; const bufferLength = analyser.frequencyBinCount; frequencyData = new Uint8Array(bufferLength); const source = audioContext.createMediaElementSource(audio); source.connect(analyser); analyser.connect(audioContext.destination); } if (audioContext.state === 'suspended') { audioContext.resume(); } audio.play().catch(error => console.error("Audio playback error:", error)); document.getElementById("instructions").style.display = "none"; }, { once: true }); // --------------------------- // Smoothing Variables for Audio-Driven Motion // --------------------------- let smoothedBass = 0, smoothedMid = 0, smoothedHigh = 0; const smoothingFactor1 = 0.01; // Adjust this value for more/less smoothing const smoothingFactor2 = 0.02; // Adjust this value for more/less smoothing const maxRotation = Math.PI / 18; // --------------------------- // Animation Loop with Smoothing and Audio Progress Update // --------------------------- function animate() { animationId = requestAnimationFrame(animate); // オーディオ進捗の表示更新 if (audio.duration && !isNaN(audio.duration)) { document.getElementById("audioProgress").textContent = formatTime(audio.currentTime) + " / " + formatTime(audio.duration); } if (analyser) { analyser.getByteFrequencyData(frequencyData); // --- Bass: indices 0-9 (scale 用) --- let bassSum = 0; for (let i = 0; i < 10; i++) { bassSum += frequencyData[i]; } let bassAvg = bassSum / 10; let bassNorm = bassAvg / 255; // --- Mid: indices 10-49 (rotation 用) --- let midSum = 0, midCount = 0; for (let i = 10; i < 50; i++) { midSum += frequencyData[i]; midCount++; } let midAvg = midSum / midCount; let midNorm = midAvg / 255; // --- High: indices 50-end (vertical movement 用) --- let highSum = 0, highCount = 0; for (let i = 50; i < frequencyData.length; i++) { highSum += frequencyData[i]; highCount++; } let highAvg = highSum / highCount; let highNorm = highAvg / 255; // 指数移動平均でスムージング smoothedBass += (bassNorm - smoothedBass) * smoothingFactor1; smoothedMid += (midNorm - smoothedMid) * smoothingFactor1; smoothedHigh += (highNorm - smoothedHigh) * smoothingFactor2; // Cube のプロパティ更新 let targetScale1 = 2 + smoothedBass * 3.0; // 1~約2.5の範囲 let targetScale2 = 2.5 + smoothedBass * 2.2; // Scale from 1 to ~2.5 cube1.scale.lerp(new THREE.Vector3(targetScale1, targetScale1, targetScale1), smoothingFactor1); // Smoothly update rotation (incremental adjustments): // cube1.rotation.x += smoothedMid * 0.0005; cube1.rotation.y += smoothedMid * 0.02; // Smooth vertical movement directly using the smoothed high frequency value: cube1.position.x = (smoothedMid + 0.2) * - 8; cube1.position.y = 0 + (smoothedMid + 0.2) * 7; // textMesh movement anggletext -= 0.1; textMesh.position.x = - 4 + radiustext * Math.cos(Math.PI / 180 * anggletext); // textMesh.position.y = - 3 + radiustext * Math.cos(Math.PI / 180 * anggletext); textMesh.position.z = 1 + radiustext * Math.sin(Math.PI / 180 * anggletext); if (audio.currentTime / audio.duration > 0.5) { cube1.rotation.x = Math.sin(Date.now() * - 0.0002) * maxRotation; }; }; // Starfield のゆっくりした回転 stars.rotation.y += 0.0005; // end event audio.addEventListener('ended', () => { spotLight.intensity = 0; // スポットライトの光量を 0 にする ambientLight.intensity = 0; // 環境ライトの光量を 0 にする document.getElementById("music_title").textContent = "Thank you for viewing." ; // 5秒後にアニメーションをキャンセル setTimeout(() => { cancelAnimationFrame(animationId);}, 5000); }); renderer.render(scene, camera); } animate(); </script> <!-- access counter --!> <table style="visibility:hidden;"> <tr><td><img src="../daycount/daycount.cgi?gif"></td><td><img src="../daycount/daycount.cgi?today"></td><td><img src="../daycount/daycount.cgi?yes"></td></tr> </table> <!-- access counter2 --!> <table id="table_ac" style="visibility:hidden;" > <tr /><td><img src="../daycount2/daycount.cgi?gif"></td><td><img src="../daycount2/daycount.cgi?today"></td> <td><img src="../daycount2/daycount.cgi?yes"></td> </table> </body> </html>

Q&A

次のコードを説明して: (

 document.body.addEventListener('click', () => {
      if (!audioContext) {
        audioContext = new (window.AudioContext || window.webkitAudioContext)();
        analyser = audioContext.createAnalyser();
        analyser.fftSize = 256;
        const bufferLength = analyser.frequencyBinCount;
        frequencyData = new Uint8Array(bufferLength);
        const source = audioContext.createMediaElementSource(audio);
        source.connect(analyser);
        analyser.connect(audioContext.destination);
      }
      if (audioContext.state === 'suspended') {
        audioContext.resume();
      }
      audio.play().catch(error => console.error("Audio playback error:", error));
      document.getElementById("instructions").style.display = "none";
    }, { once: true });

以下のコードは、ユーザーが画面をクリックしたときに Web Audio API を使ってオーディオ再生と解析の設定を行い、その後オーディオを再生する処理を実装しています。各部分の詳細は以下の通りです。 javascript document.body.addEventListener('click', () => { // 1. AudioContext(オーディオ処理全体の基盤)がまだ生成されていない場合 if (!audioContext) { // 新しい AudioContext を作成(ブラウザ間の互換性を考慮して、window.AudioContext または window.webkitAudioContext を使用) audioContext = new (window.AudioContext || window.webkitAudioContext)(); // 2. オーディオ解析用の Analyser ノードを作成 analyser = audioContext.createAnalyser(); // FFT(高速フーリエ変換)のサイズを 256 に設定 // これにより、解析される周波数データの解像度が決まる(frequencyBinCount は fftSize の半分=128 となる) analyser.fftSize = 256; // 3. Analyser ノードが出力する周波数データを格納する配列を用意 const bufferLength = analyser.frequencyBinCount; frequencyData = new Uint8Array(bufferLength); // 4. HTML のオーディオ要素 (audio) を Web Audio API 用のソースに変換 const source = audioContext.createMediaElementSource(audio); // オーディオソースから Analyser ノードへ接続 source.connect(analyser); // Analyser ノードから最終出力先(スピーカーなど)へ接続 analyser.connect(audioContext.destination); } // 5. ブラウザによっては AudioContext が初期状態で "suspended"(停止状態)になっているので、その場合は再開する if (audioContext.state === 'suspended') { audioContext.resume(); } // 6. オーディオの再生を開始(play() は Promise を返すので、エラー発生時は catch で処理) audio.play().catch(error => console.error("Audio playback error:", error)); // 7. ユーザーに表示されていた「クリックしてオーディオ開始」のインストラクションを非表示にする document.getElementById("instructions").style.display = "none"; // 8. イベントリスナーを { once: true } オプションで設定しているため、このクリックイベントは最初の1回だけ実行される }, { once: true });

各部分の説明 1. イベントリスナーの設定 - `document.body.addEventListener('click', () => { ... }, { once: true });` → ページ全体の `` に対して、ユーザーがクリックしたときに実行される関数を登録しています。`{ once: true }` を指定しているため、最初のクリック時のみ実行され、その後は自動的にリスナーが解除されます。 2. AudioContext の生成 - `if (!audioContext) { ... }` 内で、まだ AudioContext が存在しない場合に新しく作成します。 - `new (window.AudioContext || window.webkitAudioContext)();` → 最新のブラウザでは `AudioContext` を使い、古いブラウザでは `webkitAudioContext` を使います。 3. Analyser ノードの設定 - `analyser = audioContext.createAnalyser();` → オーディオデータを周波数ごとに分解するためのノードを生成します。 - `analyser.fftSize = 256;` → FFT(高速フーリエ変換)のサイズを設定し、これにより解析の細かさ(frequencyBinCount は 256/2 = 128)を決定します。 4. 周波数データ用の配列の作成 - `frequencyData = new Uint8Array(bufferLength);` → 解析結果のデータを格納するための符号なし 8 ビット整数型の配列を用意します。 5. オーディオソースの接続 - `const source = audioContext.createMediaElementSource(audio);` → HTML のオーディオ要素 `audio` を Web Audio API のソースに変換します。 - `source.connect(analyser);` と `analyser.connect(audioContext.destination);` → オーディオデータをまず Analyser に流し、さらに最終的に AudioContext の出力先(スピーカーなど)に接続します。 6. AudioContext の再開 - `if (audioContext.state === 'suspended') { audioContext.resume(); }` → ユーザーの操作前は AudioContext が一時停止状態(suspended)になっていることがあるため、クリック後に再開しています。 7. オーディオの再生 - `audio.play().catch(error => console.error("Audio playback error:", error));` → オーディオの再生を開始し、再生に失敗した場合はエラーメッセージをコンソールに出力します。 8. インストラクションの非表示 - `document.getElementById("instructions").style.display = "none";` → ユーザーに「クリックしてオーディオ開始」などの指示があれば、それを非表示にして画面をすっきりさせます。 このコード全体は、ユーザーの最初のクリックによってオーディオのセットアップおよび再生を行い、さらにオーディオデータを解析する準備を行うためのものです。これにより、後続の処理(たとえば、オーディオに連動して3Dオブジェクトを動かすなど)が可能になります。

次のコードを詳しく説明して:
cube.scale.lerp(new THREE.Vector3(targetScale, targetScale, targetScale), smoothingFactor);

このコードは、Three.js のオブジェクト(ここでは `cube`)のスケール(拡大・縮小の大きさ)を、現在の値から目標値へスムーズに変化させるために使われます。以下、各部分について詳しく説明します。 1. `cube.scale` - 意味: `cube.scale` は `THREE.Vector3` 型のオブジェクトで、立方体の各軸(x, y, z)のスケール(拡大率)を表します。 - 例: 初期状態で `cube.scale` は通常 `(1, 1, 1)` となっており、これはオブジェクトが元のサイズで表示されることを意味します。 2. `new THREE.Vector3(targetScale, targetScale, targetScale)` - 意味: ここでは、目標とするスケールを表す新しい `THREE.Vector3` オブジェクトを生成しています。 - 内容: - `targetScale` は数値で、各軸に同じ拡大率を設定するために使われます。 - つまり、立方体を均一に拡大・縮小する場合に、このように各軸に同じ値を指定します。 3. `.lerp(…, smoothingFactor)` - lerp の意味: `lerp` は「linear interpolation(線形補間)」の略で、現在のベクトルと目標のベクトルの間を、ある割合で補間(中間値を求める)するためのメソッドです。 - パラメーター: - 第一引数: 補間の目標となるベクトル(ここでは `new THREE.Vector3(targetScale, targetScale, targetScale)`)。 - 第二引数 (`smoothingFactor`): 補間の比率を表す数値です。通常、0〜1の範囲の値を取り、 - `0` なら何も変化せず、 - `1` なら目標の値に完全に切り替わります。 値が小さいほど、徐々に目標値へ近づく(スムーズに変化する)効果があります。 4. 全体の流れ - 現状: 立方体の現在のスケール(例えば、`(1, 1, 1)`)と、目標とするスケール(例えば、`(2, 2, 2)`)があり、これらの値の間を `smoothingFactor` の割合で補間します。 - 計算例: もし `smoothingFactor` が `0.1` であれば、新しいスケールは newScale = currentScale * (1 - 0.1) + targetScale * 0.1 = currentScale * 0.9 + targetScale * 0.1 となります。これにより、急激な変化ではなく、滑らかな変化が実現されます。 まとめ javascript cube.scale.lerp(new THREE.Vector3(targetScale, targetScale, targetScale), smoothingFactor); この1行のコードは、`cube` の現在のスケールベクトルを、各軸が `targetScale` の値となるベクトルに向けて、`smoothingFactor` で指定された割合だけ補間(移動)させ、徐々に目標のスケールへ変化させるという処理を行っています。これにより、視覚的に滑らかな拡大・縮小のアニメーションを実現しています。

次のコードを詳しく説明して:
smoothedBass += (bassNorm - smoothedBass) * smoothingFactor1;

この行 js smoothedBass += (bassNorm - smoothedBass) * smoothingFactor1; は、指数移動平均(Exponential Moving Average, EMA)を利用してベースの周波数値を平滑化する処理です。以下に詳しく解説します。 - bassNorm オーディオの低音部分の値を正規化(0~1の範囲に調整)したものです。 - smoothedBass これまでに計算された平滑化済みのベース値を保持している変数です。次のフレームでの値はこの変数に基づいて更新されます。 - smoothingFactor1 小さな定数(この場合は0.01)で、新しい値がどれだけ影響を与えるかを決めています。値が小さいほど変化がゆっくりになります。 実際の計算は以下のように展開できます: js smoothedBass = (1 - smoothingFactor1) * smoothedBass + smoothingFactor1 * bassNorm; つまり、 - 現在の `smoothedBass` の (1 - smoothingFactor1) の分をそのまま保持し、 - 新しい `bassNorm` の smoothingFactor1 の分を加えることで、`smoothedBass` が徐々に `bassNorm` に近づくように更新されます。これにより、音の急激な変化を滑らかに表現でき、視覚的な動きに自然な遷移が生まれます。

実例・サーバーでの実行

3D audio

機械学習

プログラミングにおける機械学習とは具体的にどのようにしているのか。そのコードを実行して正しく動作の確認もできるか

プログラミングにおける機械学習(ML)は、データを元にモデルを訓練し、パターンを学習させて推論を行うプロセスです。 機械学習の基本的な流れは以下のようになります: 1. データの準備(特徴量とラベルの用意) 2. モデルの選択(線形回帰、ニューラルネットワーク、決定木など) 3. モデルの訓練(データに基づいてパラメータを学習) 4. 予測と評価(未知のデータに対して推論し、精度を確認) 5. モデルのチューニング(ハイパーパラメータの最適化) 簡単な機械学習モデルを実装して動作確認 以下のコードでは、scikit-learn を使用して線形回帰 のモデルを学習させます。 内容 -目的: ある商品の広告費(X)と売上(Y)の関係を学習し、新しい広告費から売上を予測する。 - アルゴリズム: 線形回帰(Linear Regression) 実行コード 実際にこのコードを実行し、正しく動作するか確認します。(python)

import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error, r2_score # ダミーデータ(広告費 vs 売上) np.random.seed(42) X = np.random.rand(100, 1) * 100 # 広告費(0〜100の範囲) y = 3.5 * X + np.random.randn(100, 1) * 10 + 50 # 売上(ノイズを加えた線形関係) # 訓練データとテストデータに分割 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 線形回帰モデルの作成と学習 model = LinearRegression() model.fit(X_train, y_train) # 予測 y_pred = model.predict(X_test) # モデル評価 mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) # 結果表示 plt.scatter(X_test, y_test, label="Actual Sales", color="blue") plt.plot(X_test, y_pred, label="Predicted Sales", color="red", linewidth=2) plt.xlabel("Advertising Budget") plt.ylabel("Sales") plt.legend() plt.title(f"Linear Regression Model\nMSE: {mse:.2f}, R²: {r2:.2f}") plt.show() # モデルの係数と切片 model_coef = model.coef_[0][0] model_intercept = model.intercept_[0] model_coef, model_intercept, mse, r2
実行結果 - グラフを表示しました。青い点が実際の売上データ、赤い線が予測した売上の直線です。 - モデルが正しく学習できていることがわかります。 モデルのパラメータ - 回帰係数(傾き): 約 3.46 - 切片(y軸との交点): 約 51.43 - 平均二乗誤差(MSE): 約 65.37(誤差の大きさを示す値) - 決定係数(R²): 約0.994(1に近いほどモデルの精度が高い) 結論: この線形回帰モデルは、広告費と売上の関係をほぼ正確に予測できており、機械学習が適切に機能していることが確認できました。

感想

ChatGPTのプログラムコーディングのレベルの高さを実感した。3年ほど前からの課題を解決してくれた。

疑問点や確認したいコードにも丁寧に説明してくれる。こちらもある程度のスキルがないと適確なプロンプトが出来ない。

どのようにしてプログラミングを学習するか、聞いたところ Githubなどのオープンソースやプログラミングのドキュメントで学習するほか、機械学習もしている。ChatGPTの基盤であるGPT(Generative Pre-trained Transformer)は、大規模なニューラルネットワークを使用して、コードの文法や構造を学習する、とのこと。続いて様々なQ&Aを続けたが省略する。

現在のAIは、囲碁AIの手法を基盤としていることが広く知られている。初期の囲碁AIは、プロ棋士の棋譜を学習して人間を超える実力を身につけた。その後、AlphaZeroのように自己学習を行い、新たな戦略を生み出すようになった。今では、逆に人間がその手法を学んでいる。

補足 : 指数移動平均(Exponential Moving Average, EMA)

今回のポイントはオブジェクトの動きを指数移動平均(Exponential Moving Average, EMA)を利用して周波数値を平滑化する処理を2度目のプロンプトでChatGPTが提案したことである。

株式チャート例(ChatGPT作成)


EMAは株式の初歩段階によく説明用に使われる。点線が実際の株価、赤と青線がEMA。短期EMA(例: 12日)が長期EMA(例: 26日)を上抜けるとゴールデンクロス(買いシグナル)とされる。

この例題チャートは今回の課題として理解しやすい。オーディオデータを周波数データに分解(FFT)したものが点線、赤と青線がEMA。これを元に低音を前後(z軸)、中音を上下(y軸)、高音を回転(y軸)の動きに使っている。音楽によっては画像毎に中音と高音の使い方を逆にして組み合わせる場合もある。


戻る