線形回帰は、ある変数の値を別の変数の値に基づいて予測する教師あり機械学習手法です。予測される変数は「従属変数」と呼ばれ、他の変数の予測に使用される変数は「独立変数」と呼ばれます。線形回帰では、1つ以上の独立変数を使用して線形方程式の係数を推定します。線形回帰は、予測された出力値と期待される出力値の差を最小化する直線を生成します。
本稿では、JavaとGridDBを使用して、個人の経験年数に基づいて給与を予測する線形回帰モデルを実装します。
GridDBへのデータの書き込み
使用するデータは、個人の経験年数と給与を表します。
高速なクエリ性能など多くの利点を持つGridDBにデータを格納します。まず、Javaライブラリをインポートして、これを実現します。
import com.toshiba.mwcloud.gs.Collection;
import com.toshiba.mwcloud.gs.GSException;
import com.toshiba.mwcloud.gs.GridStore;
import com.toshiba.mwcloud.gs.GridStoreFactory;
import com.toshiba.mwcloud.gs.Query;
import com.toshiba.mwcloud.gs.RowKey;
import com.toshiba.mwcloud.gs.RowSet;
import java.util.*;
GridDBはデータをコンテナに整理し、各コンテナはJavaの静的クラスとして表現できます。データを格納するコンテナを表現するJavaの静的クラスを作成してみましょう。
static class SalaryData {
@RowKey int id;
double yearsExperience;
double salary;
}
GridDBコンテナを作成し、SalaryData
という名前を付けました。3つのカラムを持つSQLテーブルとして考えてください。
GridDBにデータを書き込むには、まずデータベースへの接続を確立する必要があります。そのためには、java.util
パッケージからProperties
ファイルを作成し、key:value
構文を使用してGridDBの認証情報を渡す必要があります。
Properties props = new Properties();
props.setProperty("notificationMember", "127.0.1.1:10001");
props.setProperty("clusterName", "myCluster");
props.setProperty("user", "admin");
props.setProperty("password", "admin");
GridStore store = GridStoreFactory.getInstance().getGridStore(props);
データベースとのやり取りには store
変数を使用します。
接続が完了したので、GridDBにデータを格納することができます。まず、データ行を定義します。
SalaryData row1 = new SalaryData();
row1.id=1;
row1.yearsExperience=1.1;
row1.salary=39343.00;
SalaryData row2 = new SalaryData();
row2.id=2;
row2.yearsExperience=1.3;
row2.salary=46205.00;
SalaryData row3 = new SalaryData();
row3.id=3;
row3.yearsExperience=1.5;
row3.salary=37731.00;
SalaryData row4 = new SalaryData();
row4.id=4;
row4.yearsExperience=2.0;
row4.salary=43525.00;
SalaryData row5 = new SalaryData();
row5.id=5;
row5.yearsExperience=2.2;
row5.salary=39891.00;
SalaryData row6 = new SalaryData();
row6.id=6;
row6.yearsExperience=2.9;
row6.salary=56642.00;
SalaryData row7 = new SalaryData();
row7.id=7;
row7.yearsExperience=3.0;
row7.salary=60150.00;
SalaryData row8 = new SalaryData();
row8.id=8;
row8.yearsExperience=3.2;
row8.salary=54445.00;
SalaryData row9 = new SalaryData();
row9.id=9;
row9.yearsExperience=3.2;
row9.salary=64445.00;
SalaryData row10 = new SalaryData();
row10.id=10;
row10.yearsExperience=3.7;
row10.salary=57189.00;
SalaryData row11 = new SalaryData();
row11.id=11;
row11.yearsExperience=3.9;
row11.salary=63218.00;
SalaryData row12 = new SalaryData();
row12.id=12;
row12.yearsExperience=4.0;
row12.salary=55794.00;
SalaryData row13 = new SalaryData();
row13.id=13;
row13.yearsExperience=4.0;
row13.salary=56957.00;
SalaryData row14 = new SalaryData();
row14.id=14;
row14.yearsExperience=4.1;
row14.salary=57081.00;
SalaryData row15 = new SalaryData();
row15.id=15;
row15.yearsExperience=4.5;
row15.salary=61111.00;
SalaryData row16 = new SalaryData();
row16.id=16;
row16.yearsExperience=4.9;
row16.salary=67938.00;
SalaryData row17 = new SalaryData();
row17.id=17;
row17.yearsExperience=5.1;
row17.salary=66029.00;
SalaryData row18 = new SalaryData();
row18.id=18;
row18.yearsExperience=5.3;
row18.salary=83088.00;
SalaryData row19 = new SalaryData();
row19.id=19;
row19.yearsExperience=5.9;
row19.salary=81363.00;
SalaryData row20 = new SalaryData();
row20.id=20;
row20.yearsExperience=6.0;
row20.salary=93940.00;
SalaryData row21 = new SalaryData();
row21.id=21;
row21.yearsExperience=6.8;
row21.salary=91738.00;
SalaryData row22 = new SalaryData();
row22.id=22;
row22.yearsExperience=7.1;
row22.salary=98273.00;
SalaryData row23 = new SalaryData();
row23.id=23;
row23.yearsExperience=7.9;
row23.salary=101302.00;
SalaryData row24 = new SalaryData();
row24.id=24;
row24.yearsExperience=8.2;
row24.salary=113812.00;
SalaryData row25 = new SalaryData();
row25.id=25;
row25.yearsExperience=8.7;
row25.salary=109431.00;
データを格納する SalaryData
コンテナを選択しましょう。
Collection<String, SalaryData> sd= store.putCollection("SalaryData", SalaryData.class);
ここで put()
関数を呼び出して、データをデータベースに書き込むことができます。
sd.put(row1);
sd.put(row2);
sd.put(row3);
sd.put(row4);
sd.put(row5);
sd.put(row6);
sd.put(row7);
sd.put(row8);
sd.put(row9);
sd.put(row10);
sd.put(row11);
sd.put(row12);
sd.put(row13);
sd.put(row14);
sd.put(row15);
sd.put(row16);
sd.put(row17);
sd.put(row18);
sd.put(row19);
sd.put(row20);
sd.put(row21);
sd.put(row22);
sd.put(row23);
sd.put(row24);
sd.put(row25);
データの取得
GridDBからデータを取得し、機械学習モデルに適用します。SalaryData
コンテナに格納されているすべてのデータを選択して返すTQLクエリを記述します。
Query<salarydata> query = sd.query("select *");
RowSet</salarydata><salarydata> rs = query.fetch(false);
double x=0;
double y=0;
double[][] data = {{x},{y}};
System.out.println("Training dataset:");
while(rs.hasNext()) {
SalaryData sd1 = rs.next();
x=sd1.yearsExperience;
y=sd1.salary;
System.out.println(x +" "+ y);
double[][] d= {{x},{y}};
data=d.clone();
}</salarydata>
select * は、SalaryDataコンテナに格納されているすべてのデータを取得するTQLクエリです。また、データベースから取得した際のyearsExperieneとsalaryの値をそれぞれ格納するために、xとyという2つの変数を定義しました。データは、dataという名前の配列に格納されています。whileループは、GridDBコンテナのすべての行を繰り返し処理するのに役立ちます。
Wekaインスタンスの作成
Weka機械学習ライブラリを使用して線形回帰モデルを適合させます。 データをWekaインスタンスに変換する必要があります。 まず、データセットの属性を作成し、FastVectorデータ構造に格納します。 次に、データセットからWekaインスタンスを作成します。
まず、属性とインスタンスを格納するためのデータ構造を作成します。
int numInstances = data[0].length;
FastVector atts = new FastVector();
List<instance> instances = new ArrayList</instance><instance>();</instance>
afor
ループを作成し、FastVector データ構造に属性を追加しながら、データ項目に反復処理を行うことができます。
for(int dim = 0; dim < 2; dim++)
{
Attribute current = new Attribute("Attribute" + dim, dim);
if(dim == 0)
{
for(int obj = 0; obj < numInstances; obj++)
{
instances.add(new SparseInstance(numInstances));
}
}
for(int obj = 0; obj < numInstances; obj++)
{
instances.get(obj).setValue(current, data[dim][obj]);
}
atts.addElement(current);
}
Instances newDataset = new Instances("Dataset", atts, instances.size());
整数変数 dim
は、属性を格納するための2次元データ構造を生成します。また、モデルの構築に使用する特定の属性を持つオブジェクトも作成しました。これらは newDataset
という名前のインスタンス変数に格納されています。
線形回帰モデルの構築
データ・インスタンスはこれで準備が整いました。それらを使用して機械学習モデルを構築することができます。まず、Wekaから必要なライブラリをインポートしましょう:
import weka.classifiers.Classifier;
import weka.classifiers.Evaluation;
import weka.core.Attribute;
import weka.core.FastVector;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.SparseInstance;
データセットにクラス属性を設定しましょう。
newDataset.setClassIndex(1);
上記のコードでは、salary
をデータセットのクラス属性として設定しています。
次に、Wekaライブラリの LinearRegression()
関数を使用して、線形回帰分類器を構築します。
for(Instance inst : instances)
newDataset.add(inst);
Classifier classifier = new weka.classifiers.functions.LinearRegression();
classifier.buildClassifier(newDataset);
この関数のインスタンスを作成し、classifier
という名前を付けました。次に、buildClassifier()
関数を呼び出して、データセットを使用して分類器を構築しました。
予測を行う
線形回帰モデルを使用して、経験年数に基づいて給与を予測してみましょう。予測を行うために、データセットの最後のインスタンスを使用します。
Instance pd = newDataset.lastInstance();
double value = classifier.classifyInstance(pd);
System.out.println(value);
pd
は、私たちのデータセットの最後のインスタンスのインスタンスです。 classifyInstance()
関数は、そのインスタンスの salary
の値を予測します。
モデルを実行
モデルを実行するには、まず次の URL から Weka API をダウンロードします。
http://www.java2s.com/Code/Jar/w/weka.htm
Wekaバージョン3.7.0を選択します。
ターミナルで次のコマンドを実行して、gridstore.jar
およびweka-3-7-0.jar
ファイルのクラス・パスを設定します。
export CLASSPATH=$CLASSPATH:/usr/share/java/gridstore.jar
export CLASSPATH=$CLASSPATH:/mnt/c/Users/user/Desktop/weka-3.7.0.jar
上記のコマンドは、ファイルの場所によって変更される場合があります。
次のコマンドを実行して、.java
ファイルをコンパイルします。
javac Salary.java
生成された.classファイルを次のコマンドで実行します。
java Salary
モデルは、その人物の給与を109431.0ドルと予測しました。
ブログの内容について疑問や質問がある場合は Q&A サイトである Stack Overflow に質問を投稿しましょう。 GridDB 開発者やエンジニアから速やかな回答が得られるようにするためにも "griddb" タグをつけることをお忘れなく。 https://stackoverflow.com/questions/ask?tags=griddb