名前 題名 ▼ takiさん > > 識別関数のテストが主な目的です。 > > 識別関数のテストではなく、機械学習のテストが目的です。 > > それで、メールのSPAM、非SPAMのデータを作成してテストしました。 > unitも別にしました。 > 関数、手続きの名前もGoogleで調べてそれらしい物に変えました。 > > 懲りずにソースを挙げます。 > > 実は理解不明な現象が起きています。 > どこが間違っているのでしょうか。困っています。 > > ソースを一度に投稿したら投稿許可サイズを超えてしまいました。 > 分割して投稿します。 > > 最初にパーセプトロンの分です。 > ------------------------------------------------------------------- > unit UnitSimplePerceptron; > > interface > > uses > Winapi.Windows, Winapi.Messages, System.Types, Unit1, System.SysUtils; > > var > InputNodeCount:integer; // 入力ノード数 > InputVector:TDoubleDynArray; // 入力ベクトル サイズはInputNodeCount + 1 > WeightVector:TDoubleDynArray; // 重みベクトル サイズはInputNodeCount + 1 > > TeachingDataCount:integer; // 教師データの数 > TeachingData :array of TDoubleDynArray; // サイズはInputNodeCount + 1 > TeachingLabel:array of Integer; // 対象 1, 非対象 -1 > > procedure SetRandomWeightVector(var AWeightVector:TDoubleDynArray); > function DiscriminantFunction(var AInputVector:TDoubleDynArray; > var AWeightVector:TDoubleDynArray):Double; > function MachineLearning(AInputNodeCount,ATeachingDataCount,Amaxloop:integer):integer; > procedure CrtTeachingData(AInputNodeCount,ATeachingDataCount:integer); > > implementation > > procedure SetRandomWeightVector(var AWeightVector:TDoubleDynArray); > var > i,lng:integer; > begin > lng := Length(AWeightVector); > Randomize; > for i := 0 to lng - 1 do begin > AWeightVector[i] := Random; // 0〜1 > end; > end; > > // 識別関数 > function DiscriminantFunction(var AInputVector:TDoubleDynArray; > var AWeightVector:TDoubleDynArray):Double; > var > i,lng:integer; > val:Double; > begin > lng := Length(AInputVector); > val := 0.0; > // AInputVector[0] := 1.0; // バイアスなので強制的に1.0へ > for i := 0 to lng - 1 do begin > val := val + AWeightVector[i] * AInputVector[i]; > end; > result := val; > end; > > // SPAMメール教師データ作成 > procedure CrtTeachingData(AInputNodeCount,ATeachingDataCount:integer); > var > i,j:integer; > begin > Randomize; > SetLength(TeachingData,ATeachingDataCount); > for i := 0 to ATeachingDataCount - 1 do begin > SetLength(TeachingData[i],AInputNodeCount + 1); > TeachingData[i][0] := 1.0; // X0 > for j := 1 to AInputNodeCount do begin // X1,X2 > TeachingData[i][j] := Random * 5.0; // 単語の出現回数 > end; > end; > > // 教師用データのラベルを設定 > SetLength(TeachingLabel,ATeachingDataCount); > for i := 0 to ATeachingDataCount - 1 do begin > // SPAM指定 > if (TeachingData[i][1] + TeachingData[i][2]) > 3.8 then begin > TeachingLabel[i] := 1; // SPAM > end else begin > TeachingLabel[i] := -1; // 非SPAM > end; > end; > end; > > // 機械学習 > function MachineLearning(AInputNodeCount,ATeachingDataCount,Amaxloop:integer):integer; > var > i,j,k,maxloop,t:integer; > rho,wx:Double; > begin > rho := 0.1; // 更新の刻み値ρ > maxloop := 0; > // 重みをランダムで設定 > SetRandomWeightVector(WeightVector); > > repeat > k := 0; // 更新のカウンタ > // 全教師データで処理 > for i := 0 to ATeachingDataCount - 1 do begin > // 教師データのXを入力し、 > for j := 0 to 2 do begin > InputVector[j] := TeachingData[i][j]; // 1 x1 x2 > end; > // 出力が正解と合っているかチェック > wx := DiscriminantFunction(InputVector,WeightVector); > { > if (wx >= 0) then begin // i番目のデータはSPAMと識別した > if TeachingLabel[i] = -1 then begin // しかし、実際は非SPAMだったので修正 > inc(k); // 更新の回数を記憶 > for j := 0 to AInputNodeCount do begin > WeightVector[j] := WeightVector[j] - rho*InputVector[j]; // 重みを更新 > end; > end; > end else begin // i番目のデータは非SPAMと識別した > if TeachingLabel[i] = 1 then begin // しかし、実際はSPAMだったので修正 > inc(k); // 更新の回数を記憶 > for j := 0 to AInputNodeCount do begin > WeightVector[j] := WeightVector[j] + rho*InputVector[j]; // 重みを更新 > end; > end; > end; > } > { 以下のコードは上のコメントアウトのコードと同等} > t := TeachingLabel[i]; // t は -1 or +1 の値をとる > if (wx * t) < 0 then begin // wx * t がマイナスの時は更新が必要な時 > inc(k); // 更新の回数を記憶 > for j := 0 to AInputNodeCount do begin > WeightVector[j] := WeightVector[j] + t * rho * InputVector[j]; // 式にtが入っている > end; > end; > { } > end; // of for 全教師データ > > inc(maxloop); // 無限ループ脱出用 > if maxloop > Amaxloop then break; > until k = 0; // 重みの更新がなくなるまで繰り返す > // 無い場合、終了 > if k = 0 then result := maxloop else result := -1; > end; > > end. GIF,JPEG,PNG画像ファイル及びLZH,ZIPファイルをアップロードできます.600 x 1200 ピクセルを超える画像は縮小表示されます(画像クリックで拡大表示). (上限122000(120k)バイト) 削除キー Link