問題は解決しました最終的には下部にある私の解決策を確認してください
最近、Mahout in Actionのchaper6(リスト6.1〜6.4)で推奨例を実行しようとしています。しかし、問題が発生し、グーグルで検索しましたが、解決策が見つかりません。
ここに問題があります:私はマッパーリデューサーのペアを持っています
public final class WikipediaToItemPrefsMapper extends
Mapper<LongWritable, Text, VarLongWritable, VarLongWritable> {
private static final Pattern NUMBERS = Pattern.compile("(\\d+)");
@Override
protected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
String line = value.toString();
Matcher m = NUMBERS.matcher(line);
m.find();
VarLongWritable userID = new VarLongWritable(Long.parseLong(m.group()));
VarLongWritable itemID = new VarLongWritable();
while (m.find()) {
itemID.set(Long.parseLong(m.group()));
context.write(userID, itemID);
}
}
}
public class WikipediaToUserVectorReducer
extends
Reducer<VarLongWritable, VarLongWritable, VarLongWritable, VectorWritable> {
public void reduce(VarLongWritable userID,
Iterable<VarLongWritable> itemPrefs, Context context)
throws IOException, InterruptedException {
Vector userVector = new RandomAccessSparseVector(Integer.MAX_VALUE, 100);
for (VarLongWritable itemPref : itemPrefs) {
userVector.set((int) itemPref.get(), 1.0f);
}
context.write(userID, new VectorWritable(userVector));
}
}
レデューサーはuserIDとuserVectorを出力し、次のようになります。98955 {590:1.0 22:1.0 9059:1.0 3:1.0 2:1.0 1:1.0}
次に、別のマッパーリデューサーのペアを使用してこのデータを処理します
public class UserVectorSplitterMapper
extends
Mapper<VarLongWritable, VectorWritable, IntWritable, VectorOrPrefWritable> {
public void map(VarLongWritable key, VectorWritable value, Context context)
throws IOException, InterruptedException {
long userID = key.get();
Vector userVector = value.get();
Iterator<Vector.Element> it = userVector.iterateNonZero();
IntWritable itemIndexWritable = new IntWritable();
while (it.hasNext()) {
Vector.Element e = it.next();
int itemIndex = e.index();
float preferenceValue = (float) e.get();
itemIndexWritable.set(itemIndex);
context.write(itemIndexWritable,
new VectorOrPrefWritable(userID, preferenceValue));
}
}
}
ジョブを実行しようとすると、キャストエラーが表示されます
org.apache.hadoop.io.Textをorg.apache.mahout.math.VectorWritableにキャストできません
最初のmapper-reducerが出力をhdfsに書き込み、2番目のmapper-reducerが出力を読み取ろうとすると、マッパーは98955をVarLongWritableにキャストできますが、変換できません{590:1.0 22:1.0 9059:1.0 3: 1.0 2:1.0 1:1.0}をVectorWritableに変換します。したがって、最初のマッパーリデューサーが出力を2番目のペアに直接送信する方法があるので、データ変換を行う必要はありません。私は実際にHadoopを調べましたが、hadoop:決定的なガイドです。そのような方法はないようですが、何か提案はありますか?
問題が解決しました
解決策:SequenceFileOutputFormatを使用すると、最初のMapReduceワークフローのリデュース結果をDFSに出力して保存できます。次に、2番目のMapReduceワークフローは、マッパーの作成時にSequenceFileInputFormatクラスをパラメーターとして使用して、一時ファイルを入力として読み取ることができます。ベクトルは特定の形式のバイナリシーケンスファイルに保存されるため、SequenceFileInputFormatはそれを読み取り、ベクトル形式に戻すことができます。
次にいくつかのサンプルコードを示します。
confFactory ToItemPrefsWorkFlow = new confFactory
(new Path("/dbout"), //input file path
new Path("/mahout/output.txt"), //output file path
TextInputFormat.class, //input format
VarLongWritable.class, //mapper key format
Item_Score_Writable.class, //mapper value format
VarLongWritable.class, //reducer key format
VectorWritable.class, //reducer value format
**SequenceFileOutputFormat.class** //The reducer output format
);
ToItemPrefsWorkFlow.setMapper( WikipediaToItemPrefsMapper.class);
ToItemPrefsWorkFlow.setReducer(WikipediaToUserVectorReducer.class);
JobConf conf1 = ToItemPrefsWorkFlow.getConf();
confFactory UserVectorToCooccurrenceWorkFlow = new confFactory
(new Path("/mahout/output.txt"),
new Path("/mahout/UserVectorToCooccurrence"),
SequenceFileInputFormat.class, //notice that the input format of mapper of the second work flow is now SequenceFileInputFormat.class
//UserVectorToCooccurrenceMapper.class,
IntWritable.class,
IntWritable.class,
IntWritable.class,
VectorWritable.class,
SequenceFileOutputFormat.class
);
UserVectorToCooccurrenceWorkFlow.setMapper(UserVectorToCooccurrenceMapper.class);
UserVectorToCooccurrenceWorkFlow.setReducer(UserVectorToCooccurrenceReducer.class);
JobConf conf2 = UserVectorToCooccurrenceWorkFlow.getConf();
JobClient.runJob(conf1);
JobClient.runJob(conf2);
これで問題が発生した場合は、お気軽にご連絡ください