java - ¿Cómo construyo/ejecuto este sencillo programa Mahout sin obtener excepciones?
hadoop (4)
Debe usar el archivo JAR "de trabajo" provisto por Mahout. Empaqueta todas las dependencias. También debe agregar sus clases. Así es como funcionan todos los ejemplos de Mahout. No debe poner jarras Mahout en la biblioteca de Hadoop ya que ese tipo de "instala" un programa demasiado profundamente en Hadoop.
Me gustaría ejecutar este código que encontré en Mahout In Action:
package org.help;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.SequenceFile;
import org.apache.hadoop.io.Text;
import org.apache.mahout.math.DenseVector;
import org.apache.mahout.math.NamedVector;
import org.apache.mahout.math.VectorWritable;
public class SeqPrep {
public static void main(String args[]) throws IOException{
List<NamedVector> apples = new ArrayList<NamedVector>();
NamedVector apple;
apple = new NamedVector(new DenseVector(new double[]{0.11, 510, 1}), "small round green apple");
apples.add(apple);
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path path = new Path("appledata/apples");
SequenceFile.Writer writer = new SequenceFile.Writer(fs, conf, path, Text.class, VectorWritable.class);
VectorWritable vec = new VectorWritable();
for(NamedVector vector : apples){
vec.set(vector);
writer.append(new Text(vector.getName()), vec);
}
writer.close();
SequenceFile.Reader reader = new SequenceFile.Reader(fs, new Path("appledata/apples"), conf);
Text key = new Text();
VectorWritable value = new VectorWritable();
while(reader.next(key, value)){
System.out.println(key.toString() + " , " + value.get().asFormatString());
}
reader.close();
}
}
Lo compilo con:
$ javac -classpath :/usr/local/hadoop-1.0.3/hadoop-core-1.0.3.jar:/home/hduser/mahout/trunk/core/target/mahout-core-0.8-SNAPSHOT.jar:/home/hduser/mahout/trunk/core/target/mahout-core-0.8-SNAPSHOT-job.jar:/home/hduser/mahout/trunk/core/target/mahout-core-0.8-SNAPSHOT-sources.jar -d myjavac/ SeqPrep.java
Lo sacudí:
$ jar -cvf SeqPrep.jar -C myjavac/ .
Ahora me gustaría ejecutarlo en mi nodo hadoop local. He intentado:
hadoop jar SeqPrep.jar org.help.SeqPrep
Pero entiendo:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/mahout/math/Vector
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at org.apache.hadoop.util.RunJar.main(RunJar.java:149)
Así que traté de usar el parámetro libjars:
$ hadoop jar SeqPrep.jar org.help.SeqPrep -libjars /home/hduser/mahout/trunk/core/target/mahout-core-0.8-SNAPSHOT.jar -libjars /home/hduser/mahout/trunk/core/target/mahout-core-0.8-SNAPSHOT-job.jar -libjars /home/hduser/mahout/trunk/core/target/mahout-core-0.8-SNAPSHOT-sources.jar -libjars /home/hduser/mahout/trunk/math/target/mahout-math-0.8-SNAPSHOT.jar -libjars /home/hduser/mahout/trunk/math/target/mahout-math-0.8-SNAPSHOT-sources.jar
y tengo el mismo problema No sé qué más probar.
Mi objetivo final es poder leer un archivo .csv en el hadoop fs en una matriz dispersa y luego multiplicarlo por un vector aleatorio.
editar: Parece que Razvan lo consiguió (nota: vea a continuación otra forma de hacer esto que no ensucie su instalación de hadoop). Para referencia:
$ find /usr/local/hadoop-1.0.3/. |grep mah
/usr/local/hadoop-1.0.3/./lib/mahout-core-0.8-SNAPSHOT-tests.jar
/usr/local/hadoop-1.0.3/./lib/mahout-core-0.8-SNAPSHOT.jar
/usr/local/hadoop-1.0.3/./lib/mahout-core-0.8-SNAPSHOT-job.jar
/usr/local/hadoop-1.0.3/./lib/mahout-core-0.8-SNAPSHOT-sources.jar
/usr/local/hadoop-1.0.3/./lib/mahout-math-0.8-SNAPSHOT-sources.jar
/usr/local/hadoop-1.0.3/./lib/mahout-math-0.8-SNAPSHOT-tests.jar
/usr/local/hadoop-1.0.3/./lib/mahout-math-0.8-SNAPSHOT.jar
y entonces:
$hadoop jar SeqPrep.jar org.help.SeqPrep
small round green apple , small round green apple:{0:0.11,1:510.0,2:1.0}
edit: estoy tratando de hacer esto sin copiar las jarras mahout en la librería hadoop /
$ rm /usr/local/hadoop-1.0.3/lib/mahout-*
y luego por supuesto:
hadoop jar SeqPrep.jar org.help.SeqPrep
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/mahout/math/Vector
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at org.apache.hadoop.util.RunJar.main(RunJar.java:149)
Caused by: java.lang.ClassNotFoundException: org.apache.mahout.math.Vector
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
y cuando pruebo el archivo de trabajo mahout:
$hadoop jar ~/mahout/trunk/core/target/mahout-core-0.8-SNAPSHOT-job.jar org.help.SeqPrep
Exception in thread "main" java.lang.ClassNotFoundException: org.help.SeqPrep
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at org.apache.hadoop.util.RunJar.main(RunJar.java:149)
Si trato de incluir el archivo .jar que hice:
$ hadoop jar ~/mahout/trunk/core/target/mahout-core-0.8-SNAPSHOT-job.jar SeqPrep.jar org.help.SeqPrep
Exception in thread "main" java.lang.ClassNotFoundException: SeqPrep.jar
editar: Aparentemente, solo puedo enviar un contenedor a la vez para hadoop. Esto significa que necesito agregar la clase que hice en el archivo de trabajo mahout core:
~/mahout/trunk/core/target$ cp mahout-core-0.8-SNAPSHOT-job.jar mahout-core-0.8-SNAPSHOT-job.jar_backup
~/mahout/trunk/core/target$ cp ~/workspace/seqprep/bin/org/help/SeqPrep.class .
~/mahout/trunk/core/target$ jar uf mahout-core-0.8-SNAPSHOT-job.jar SeqPrep.class
Y entonces:
~/mahout/trunk/core/target$ hadoop jar mahout-core-0.8-SNAPSHOT-job.jar org.help.SeqPrep
Exception in thread "main" java.lang.ClassNotFoundException: org.help.SeqPrep
edit: Ok, ahora puedo hacerlo sin meterme con mi instalación de hadoop. Estaba actualizando el error .jar en esa edición anterior. Debería ser:
~/mahout/trunk/core/target$ jar uf mahout-core-0.8-SNAPSHOT-job.jar org/help/SeqPrep.class
entonces:
~/mahout/trunk/core/target$ hadoop jar mahout-core-0.8-SNAPSHOT-job.jar org.help.SeqPrep
small round green apple , small round green apple:{0:0.11,1:510.0,2:1.0}
<dependency>
<groupId>org.apache.mahout</groupId>
<artifactId>mahout-math</artifactId>
<version>0.7</version>
</dependency>
<dependency>
<groupId>org.apache.mahout</groupId>
<artifactId>mahout-collections</artifactId>
<version>1.0</version>
</dependency>
si va a tomar el código de ejemplos del https://github.com/tdunning/MiA repository, entonces contiene el archivo pom.xml
listo para usar para Maven. Y cuando compile el código con el mvn package
, creará mia-0.1-job.jar
en el directorio de target
; este archivo contiene todas las dependencias, excepto Hadoop, por lo que puede ejecutarlo en el clúster de Hadoop sin problemas.
Lo que hice fue establecer HADOOP_CLASSPATH con mi jar y todos los archivos mahout jar como se muestra a continuación.
exportar HADOOP_CLASSPATH = / home / xxx / my.jar: /opt/cloudera/parcels/CDH-4.3.0-1.cdh4.3.0.p0.22/lib/mahout/mahout-core-0.7-cdh4.3.0.jar : /opt/cloudera/parcels/CDH-4.3.0-1.cdh4.3.0.p0.22/lib/mahout/mahout-core-0.7-cdh4.3.0-job.jar: / opt / cloudera / parcels / CDH -4.3.0-1.cdh4.3.0.p0.22 / lib / mahout / mahout-examples-0.7-cdh4.3.0.jar: /opt/cloudera/parcels/CDH-4.3.0-1.cdh4.3.0. p0.22 / lib / mahout / mahout-examples-0.7-cdh4.3.0-job.jar: /opt/cloudera/parcels/CDH-4.3.0-1.cdh4.3.0.p0.22/lib/mahout/mahout -integration-0.7-cdh4.3.0.jar: /opt/cloudera/parcels/CDH-4.3.0-1.cdh4.3.0.p0.22/lib/mahout/mahout-math-0.7-cdh4.3.0.jar
Luego pude ejecutar hadoop com.mycompany.mahout.CSVtoVector iris / nb / iris1.csv iris / nb / data / iris.seq
Así que debes incluir todos tus frascos y el frasco mahout en HADOOP_CLASSPATH y luego puedes ejecutar tu clase con
hadoop <classname>