When integrating R with Java with RCaller, I never get back any variable that is created within the script. There seems to be a fundamental missunderstanding how RCaller works. Isn't it that all the variables in the Environment can be parsed from Java? How?
#Test
public void test() {
RCaller caller = new RCaller();
RCode code = new RCode();
caller.setRscriptExecutable("/usr/bin/Rscript");
caller.runAndReturnResult("source('~/git/conjoint_it/src/main/r/a.R')");
System.out.println(caller.getParser().getNames());
}
a.R:
...
m3 <- mlogit(choice ~ 0 + seat + cargo + eng
+ as.numeric(as.character(price)),
data = cbc.mlogit)
su = summary(m3)
m3 #last line
this returns only [visible]
you can handle all of the variables defined in an environment with RCaller.
Now we suppose you use the global environment (this is a special and the top level environment in which you declare variables out of a refclass or a function).
package org.expr.rcaller;
import java.util.ArrayList;
import org.expr.rcaller.Globals;
import org.expr.rcaller.RCaller;
import org.expr.rcaller.RCode;
import org.junit.Test;
import org.junit.Assert;
public class HandlingAllVariablesTest {
private final static double delta = 1.0 / 1000.0;
#Test
public void GetAllVariablesInEnvironmentTest() {
RCaller caller = new RCaller();
Globals.detect_current_rscript();
caller.setRscriptExecutable(Globals.Rscript_current);
RCode code = new RCode();
code.addDouble("x", 5.65);
code.addDouble("y", 8.96);
code.addRCode("result <- as.list(.GlobalEnv)");
caller.setRCode(code);
caller.runAndReturnResult("result");
ArrayList<String> names = caller.getParser().getNames();
System.out.println("Names : " + names);
System.out.println("x is " + caller.getParser().getAsDoubleArray("x")[0]);
System.out.println("y is " + caller.getParser().getAsDoubleArray("y")[0]);
Assert.assertEquals(caller.getParser().getAsDoubleArray("x")[0], 5.65, delta);
Assert.assertEquals(caller.getParser().getAsDoubleArray("y")[0], 8.96, delta);
}}
Results like this:
Names : [x, y]
x is 5.65
y is 8.96
Here is the key point
code.addRCode("result <- as.list(.GlobalEnv)");
so we are defining a variable to capture all of the variables defined in the global environment. as.list() function converts an environment object into a list. The second important point is to transfer this variable into the java by
caller.runAndReturnResult("result");
You can see more examples about capturing specific variables rather than environments by visiting the blog page and the web page.
Imports:
import com.github.rcaller.rStuff.RCaller;
import com.github.rcaller.rStuff.RCode;
Java code:
RCaller caller = new RCaller();
RCode code = new RCode();
caller.setRscriptExecutable("C:\\Program Files\\R\\R-4.0.2\\bin\\Rscript.exe");
caller.setRCode(code);
code.clear();
caller.cleanRCode();
//Methods to parse variables to the Rscript
code.addInt("mydata1", 5);
code.addDoubleArray("mydata2", new double[]{1, 2, 3, 4, 5});
code.addRCode("mydata3 <- 'Data'");
//Calling the Rscript
code.addRCode("source('./src/test.r')");
//Reciving Values from the Rscript through the result variable
caller.runAndReturnResult("result");
int data = caller.getParser().getAsIntArray("data")[0];
double mean = caller.getParser().getAsDoubleArray("mean")[0];
String text = caller.getParser().getAsStringArray("text")[0];
System.out.println(data);
System.out.println(mean);
System.out.println(text);
test.r:
result1 <- mydata1 * 2
result2 <- mean(mydata2)
result3 <- paste("Result3", mydata3, sep=" ")
result <- list(data=result1, mean=result2, text=result3)
Output:
10
3.0
Result3 Data
Related
I'm trying to calculate the best match for a given address with the kNN algorithm in TensorFlow, which works pretty good, but when I'm trying to export the model and use it in our Java Environment I got stuck on how to feed the sparse placholders from Java.
Here is a pretty much stripped down version of the python part, which returns the smallest distance between the test name and the best reference name. So far this work's as expected. When I export the model and import it in my Java program it always returns the same value (distance of the placeholders default). I asume, that the python function sparse_from_word_vec(word_vec) isn't in the model, which would totally make sense to me, but then how should i make this sparse tensor? My input is a single string and I need to create a fitting sparse tensor (value) to calculate the distance. I also searched for a way to generate the sparse tensor on the Java side, but without success.
import tensorflow as tf
import pandas as pd
d = {'NAME': ['max mustermann',
'erika musterfrau',
'joseph haydn',
'johann sebastian bach',
'wolfgang amadeus mozart']}
df = pd.DataFrame(data=d)
input_name = tf.placeholder_with_default('max musterman',(), name='input_name')
output_dist = tf.placeholder(tf.float32, (), name='output_dist')
test_name = tf.sparse_placeholder(dtype=tf.string)
ref_names = tf.sparse_placeholder(dtype=tf.string)
output_dist = tf.edit_distance(test_name, ref_names, normalize=True)
def sparse_from_word_vec(word_vec):
num_words = len(word_vec)
indices = [[xi, 0, yi] for xi,x in enumerate(word_vec) for yi,y in enumerate(x)]
chars = list(''.join(word_vec))
return(tf.SparseTensorValue(indices, chars, [num_words,1,1]))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
t_data_names=tf.constant(df['NAME'])
reference_names = [el.decode('UTF-8') for el in (t_data_names.eval())]
sparse_ref_names = sparse_from_word_vec(reference_names)
sparse_test_name = sparse_from_word_vec([str(input_name.eval().decode('utf-8'))]*5)
feeddict={test_name: sparse_test_name,
ref_names: sparse_ref_names,
}
output_dist = sess.run(output_dist, feed_dict=feeddict)
output_dist = tf.reduce_min(output_dist, 0)
print(output_dist.eval())
tf.saved_model.simple_save(sess,
"model-simple",
inputs={"input_name": input_name},
outputs={"output_dist": output_dist})
And here is my Java method:
public void run(ApplicationArguments args) throws Exception {
log.info("Loading model...");
SavedModelBundle savedModelBundle = SavedModelBundle.load("/model", "serve");
byte[] test_name = "Max Mustermann".toLowerCase().getBytes("UTF-8");
List<Tensor<?>> output = savedModelBundle.session().runner()
.feed("input_name", Tensor.<String>create(test_names))
.fetch("output_dist")
.run();
System.out.printl("Nearest distance: " + output.get(0).floatValue());
}
I was able to get your example working. I have a couple of comments on your python code before diving in.
You use the variable output_dist for 3 different value types throughout the code. I'm not a python expert, but I think it's bad practice. You also never actually use the input_name placeholder, except for exporting it as an input. Last one is that tf.saved_model.simple_save is deprecated, and you should use the tf.saved_model.Builder instead.
Now for the solution.
Looking at the libtensorflow jar file using the command jar tvf libtensorflow-x.x.x.jar (thanks to this post), you can see that there are no useful bindings for creating a sparse tensor (maybe make a feature request?). So we have to change the input to a dense tensor, then add operations to the graph to convert it to sparse. In your original code the sparse conversion was on the python side which means that the loaded graph in java wouldn't have any ops for it.
Here is the new python code:
import tensorflow as tf
import pandas as pd
def model():
#use dense tensors then convert to sparse for edit_distance
test_name = tf.placeholder(shape=(None, None), dtype=tf.string, name="test_name")
ref_names = tf.placeholder(shape=(None, None), dtype=tf.string, name="ref_names")
#Java Does not play well with the empty character so use "/" instead
test_name_sparse = tf.contrib.layers.dense_to_sparse(test_name, "/")
ref_names_sparse = tf.contrib.layers.dense_to_sparse(ref_names, "/")
output_dist = tf.edit_distance(test_name_sparse, ref_names_sparse, normalize=True)
#output the index to the closest ref name
min_idx = tf.argmin(output_dist)
return test_name, ref_names, min_idx
#Python code to be replicated in Java
def pad_string(s, max_len):
return s + ["/"] * (max_len - len(s))
d = {'NAME': ['joseph haydn',
'max mustermann',
'erika musterfrau',
'johann sebastian bach',
'wolfgang amadeus mozart']}
df = pd.DataFrame(data=d)
input_name = 'max musterman'
#pad dense tensor input
max_len = max([len(n) for n in df['NAME']])
test_input = [list(input_name)]*len(df['NAME'])
#no need to pad, all same length
ref_input = list(map(lambda x: pad_string(x, max_len), [list(n) for n in df['NAME']]))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
test_name, ref_names, min_idx = model()
#run a test to make sure the model works
feeddict = {test_name: test_input,
ref_names: ref_input,
}
out = sess.run(min_idx, feed_dict=feeddict)
print("test output:", out)
#save the model with the new Builder API
signature_def_map= {
"predict": tf.saved_model.signature_def_utils.predict_signature_def(
inputs= {"test_name": test_name, "ref_names": ref_names},
outputs= {"min_idx": min_idx})
}
builder = tf.saved_model.Builder("model")
builder.add_meta_graph_and_variables(sess, ["serve"], signature_def_map=signature_def_map)
builder.save()
And here is the java to load and run it. There is probably a lot of room for improvement here (java isn't my main language), but it gives you the idea.
import org.tensorflow.Graph;
import org.tensorflow.Session;
import org.tensorflow.Tensor;
import org.tensorflow.TensorFlow;
import org.tensorflow.SavedModelBundle;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
public class Test {
public static byte[][] makeTensor(String s, int padding) throws Exception
{
int len = s.length();
int extra = padding - len;
byte[][] ret = new byte[len + extra][];
for (int i = 0; i < len; i++) {
String cur = "" + s.charAt(i);
byte[] cur_b = cur.getBytes("UTF-8");
ret[i] = cur_b;
}
for (int i = 0; i < extra; i++) {
byte[] cur = "/".getBytes("UTF-8");
ret[len + i] = cur;
}
return ret;
}
public static byte[][][] makeTensor(List<String> l, int padding) throws Exception
{
byte[][][] ret = new byte[l.size()][][];
for (int i = 0; i < l.size(); i++) {
ret[i] = makeTensor(l.get(i), padding);
}
return ret;
}
public static void main(String[] args) throws Exception {
System.out.println("Loading model...");
SavedModelBundle savedModelBundle = SavedModelBundle.load("model", "serve");
List<String> str_test_name = Arrays.asList("Max Mustermann",
"Max Mustermann",
"Max Mustermann",
"Max Mustermann",
"Max Mustermann");
List<String> names = Arrays.asList("joseph haydn",
"max mustermann",
"erika musterfrau",
"johann sebastian bach",
"wolfgang amadeus mozart");
//get the max length for each array
int pad1 = str_test_name.get(0).length();
int pad2 = 0;
for (String var : names) {
if(var.length() > pad2)
pad2 = var.length();
}
byte[][][] test_name = makeTensor(str_test_name, pad1);
byte[][][] ref_names = makeTensor(names, pad2);
//use a with block so the close method is called
try(Tensor t_test_name = Tensor.<String>create(test_name))
{
try (Tensor t_ref_names = Tensor.<String>create(ref_names))
{
List<Tensor<?>> output = savedModelBundle.session().runner()
.feed("test_name", t_test_name)
.feed("ref_names", t_ref_names)
.fetch("ArgMin")
.run();
System.out.println("Nearest distance: " + output.get(0).longValue());
}
}
}
}
Main Class
package main;
import static org.junit.Assert.*;
import java.util.ArrayList;
import org.junit.Test;
import lib.Die;
import lib.Name;
import lib.PairOfDice;
import lib.Player;
public class PlayerAppTest {
/* Please note - when we come to mark the solution to this unit test we will change the input
* data set for the players added to the list to ensure the solution works dynamically based
* upon any given data set and is not hardcoded in any way.
*/
#Test
public void testExecute() {
ArrayList<Player> players = new ArrayList<>();
players.add(new Player(new Name("Joe", "Bloggs"), new PairOfDice()));
players.add(new Player(new Name("Fred", "Jones"), new Die()));
players.add(new Player(new Name("Nila", "Singh"), new PairOfDice(new Die(5), new Die(5))));
String result = PlayerApp.execute(players, "Cassie Downturn");
String expectedResult = "cassie, DOWNTURN\nnila, SINGH\n";
assertEquals("The string returned should match the expected result (run 1)", expectedResult, result);
/* Test with a second set of input data */
ArrayList<Player> players2 = new ArrayList<>();
players2.add(new Player(new Name("David", "Blunt"), new PairOfDice()));
players2.add(new Player(new Name("Tim", "Jonas"), new Die(5)));
players2.add(new Player(new Name("Remi", "Patel"), new Die()));
String result2 = PlayerApp.execute(players2, "Cassie Downturn");
String expectedResult2 = "cassie, DOWNTURN\ntim, JONAS\nremi, PATEL\n";
assertEquals("The string returned should match the expected result (run 2)", expectedResult2, result2);
}
}
Hello, this is the JUnit test which I have to pass, below is the code that I have written in my main package;
JUnit Test Class
package main;
import java.util.ArrayList;
import lib.Player;
public class PlayerApp {
public static String execute(ArrayList<Player> players, String fullName) {
players.get(0).setFullPlayerName(fullName);
fullName = "";
for (int i = 0; i <players.size(); i ++) {
if (players.get(i).getName().getFirstName().toLowerCase().contains("a") || players.get(i).getName().getFamilyName().toUpperCase().contains("a")) {
fullName = players.get(i).getName().getFirstName().toLowerCase() + ", " + players.get(i).getName().getFamilyName().toUpperCase() + "\n";
}
System.out.println(fullName);
}
return fullName;
}
}
This is the code in my main package, I am trying to print out the names which contain a char "a" in the first name, the first name should be lowercase and the family name should be uppercase. It should print out
cassie, DOWNTURN
nila, SINGH which is the names with a new line between them, however, when i print it, it prints the following;
cassie, DOWNTURN
cassie, DOWNTURN
nila, SINGH
I am confused as to why cassie, DOWNTURN has been printed twice as i cannot find the error in my code, any help would be greatly appreciated, thank you.
You will print it even if the if doesn't match as it's outside the if-statement. Move it inside instead.
for (int i = 0; i <players.size(); i ++) {
if (players.get(i).getName().getFirstName().toLowerCase().contains("a") || players.get(i).getName().getFamilyName().toUpperCase().contains("a")) {
fullName = players.get(i).getName().getFirstName().toLowerCase() + ", " + players.get(i).getName().getFamilyName().toUpperCase() + "\n";
System.out.println(fullName);
}
}
Your print statement is not conditional and will always execute, move it inside the if. You're printing twice as your are not changing the value in fullName if the if condition does not evaluate as true. Further your family name comparison will always be false as you're comparing upper and lower case.
Your code can also be tided up and made easier to read:
for(Player player : players){
if(player.getName().getFirstName()).toLowerCase().contains("a")||player.getName().getFamilyName().toUpperCase.contains("A"))){
String fullName = players.get(i).getName().getFirstName().toLowerCase() + ", " + players.get(i).getName().getFamilyName().toUpperCase() + "\n";
System.out.println(fullname);
}
}
The last line of the code below gives the following error: " expected
illegal start of type
package arrEmpleados does not exist"
package javaPrueba2;
import java.util.ArrayList;
class Principal {
ArrayList<Empleado> arrEmpleados = new ArrayList<Empleado>();
arrEmpleados.add(new Empleado(541000, 2400.0, 40.0, 16, 20.0, 2));
Empleado is a class in another file. That one, this one and the main are all in the package javaPrueba2 displayed in the 1st line...
The same error is returned if I just create a simple string ArrayList
ArrayList<String> arrEmpleados = new ArrayList();
arrEmpleados.add("ana"));
What's going on? I almost copied the way to do the ArrayList from here:
StackOverflow: Creating an Arraylist of Objects
So if this is wrong, how should I do it?
EDIT:
Per request, this is the Empleado Class:
package javaPrueba2;
public class Empleado{
int nif, horasExtra, numHijos; // horasExtra son mensuales
double sueldoBase, pagoHora, porcIRPF;
Empleado(int nif, double sueldoBase, double pagoHora, int horasExtra, double porcIRPF, int numHijos){
this.nif = nif;
this.sueldoBase = sueldoBase;
this.pagoHora = pagoHora;
this.horasExtra = horasExtra;
this.porcIRPF = porcIRPF;
this.numHijos = numHijos;
}
//Calcula el complemento por horas extras realizadas
double complemento(){
return pagoHora * horasExtra;
}
//Calcula el sueldo bruto
double bruto(){
return sueldoBase + this.complemento();
}
//Calcula las retenciones
double retenciones(){
int puntosDescuento;
double porcentajeFinal;
if (numHijos > 2){
puntosDescuento = 2;
} else puntosDescuento = 1;
porcentajeFinal = porcIRPF - puntosDescuento;
return porcentajeFinal * this.bruto() / 100;
}
}
You should start to learn Basics from Java, instructions can only be in methods (or static block)
class Principal {
ArrayList<Empleado> arrEmpleados = new ArrayList<Empleado>();
public void addAEmpleado(){
arrEmpleados.add(new Empleado(541000, 2400.0, 40.0, 16, 20.0, 2));
}
}
Although I want to use feed and fetch functions in TensorFlowInferenceInterface, I can't understand feed and fetch args.
public void feed(String inputName, float[] src, long... dims)
public void fetch(String outputName, float[] dst)
Here is TensorflowInferenceInterface.↓
https://github.com/tensorflow/tensorflow/blob/r1.4/tensorflow/contrib/android/java/org/tensorflow/contrib/android/TensorFlowInferenceInterface.java
Now, I use Android-Studio and want to import program using MNIST.
Here is program that make protocol buffer.
import tensorflow as tf
import shutil
import os.path
if os.path.exists("./tmp/beginner-export"):
shutil.rmtree("./tmp/beginner-export")
# Import data
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./tmp/data/", one_hot=True)
g = tf.Graph()
with g.as_default():
# Create the model
x = tf.placeholder("float", [None, 784])
W = tf.Variable(tf.zeros([784, 10]), name="vaiable_W")
b = tf.Variable(tf.zeros([10]), name="variable_b")
y = tf.nn.softmax(tf.matmul(x, W) + b)
# Define loss and optimizer
y_ = tf.placeholder("float", [None, 10])
cross_entropy = -tf.reduce_sum(y_ * tf.log(y))
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
sess = tf.Session()
# Train
init = tf.initialize_all_variables()
sess.run(init)
for i in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
train_step.run({x: batch_xs, y_: batch_ys}, sess)
# Test trained model
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print(accuracy.eval({x: mnist.test.images, y_: mnist.test.labels}, sess))
# Store variable
_W = W.eval(sess)
_b = b.eval(sess)
sess.close()
# Create new graph for exporting
g_2 = tf.Graph()
with g_2.as_default():
# Reconstruct graph
x_2 = tf.placeholder("float", [None, 784], name="input")
W_2 = tf.constant(_W, name="constant_W")
b_2 = tf.constant(_b, name="constant_b")
y_2 = tf.nn.softmax(tf.matmul(x_2, W_2) + b_2, name="output")
sess_2 = tf.Session()
init_2 = tf.initialize_all_variables();
sess_2.run(init_2)
graph_def = g_2.as_graph_def()
tf.train.write_graph(graph_def, './tmp/beginner-export',
'beginner-graph.pb', as_text=False)
# Test trained model
y__2 = tf.placeholder("float", [None, 10])
correct_prediction_2 = tf.equal(tf.argmax(y_2, 1), tf.argmax(y__2, 1))
accuracy_2 = tf.reduce_mean(tf.cast(correct_prediction_2, "float"))
print(accuracy_2.eval({x_2: mnist.test.images, y__2: mnist.test.labels}, sess_2))
placeholder name for input is "input".
placeholder name for output is "output".
Please tell me feed and fetch usage.
I have given a sample code with the comments. hope you will understand.
private static final String INPUT_NODE = "input:0"; // input tensor name
private static final String OUTPUT_NODE = "output:0"; // output tensor name
private static final String[] OUTPUT_NODES = {"output:0"};
private static final int OUTPUT_SIZE = 10; // number of classes
private static final int INPUT_SIZE = 784; // size of the input
INPUT_IMAGE //MNIST Image
float[] result = new float[OUTPUT_SIZE]; // get the output probabilities for each class
inferenceInterface.feed(INPUT_NODE, INPUT_IMAGE, 1, INPUT_SIZE); //1-D input (1,INPUT_SIZE)
inferenceInterface.run(OUTPUT_NODES);
inferenceInterface.fetch(OUTPUT_NODE, result);
For the Android Tensorflow library version that I'm using, I need to give a 1-D input. Therefore, the Tensorflow code needs to modify according to that,
x_2 = tf.placeholder("float", [None, 1, 784], name="input") //1-D input
x_2 = tf.reshape(x_2,[-1, 784]) // reshape according to the model requirements
Hope this helps.
I'm currently following the Jena API inferencing tutorial:
https://jena.apache.org/documentation/inference/
and as an exercise to test my understanding, I'd like to rewrite the first example, which demonstrates a trivial RDFS reasoning from a programmatically built model:
import com.hp.hpl.jena.rdf.model.*;
import com.hp.hpl.jena.vocabulary.*;
public class Test1 {
static public void main(String...argv) {
String NS = "foo:";
Model m = ModelFactory.createDefaultModel();
Property p = m.createProperty(NS, "p");
Property q = m.createProperty(NS, "q");
m.add(p, RDFS.subPropertyOf, q);
m.createResource(NS + "x").addProperty(p, "bar");
InfModel im = ModelFactory.createRDFSModel(m);
Resource x = im.getResource(NS + "x");
// verify that property q of x is "bar" (which follows
// from x having property p, and p being a subproperty of q)
System.out.println("Statement: " + x.getProperty(q));
}
}
to something which does the same, but with the model read from this Turtle file instead (which is my own translation of the above, and thus might be buggy):
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
#prefix foo: <http://example.org/foo#>.
foo:p a rdf:Property.
foo:q a rdf:Property.
foo:p rdfs:subPropertyOf foo:q.
foo:x foo:p "bar".
with this code:
public class Test2 {
static public void main(String...argv) {
String NS = "foo:";
Model m = ModelFactory.createDefaultModel();
m.read("foo.ttl");
InfModel im = ModelFactory.createRDFSModel(m);
Property q = im.getProperty(NS + "q");
Resource x = im.getResource(NS + "x");
System.out.println("Statement: " + x.getProperty(q));
}
}
which doesn't seem to be the right approach (I suspect in particular that my extraction of the q property is somehow not right). What am I doing wrong?
String NS = "foo:";
m.createResource(NS + "x")
creates a URI but the Turtle version has foo:x = http://example.org/foo#x
See the differences by printing the model im.write(System.out, "TTL");
Change NS = "foo:" to NS = "http://example.org/foo#"