I am new to TBB, so my apologies, if this question is obvious... but how do I set up an aggregating node with TBB? Out of all pre-made nodes I cannot find the right type for it.
Imagine I have a stream of incoming images. I want a node that keeps accepting images (with a FIFO buffer), does some calculation on them (i.e. it needs an internal state) and whenever it has received N images (fixed parameter), it emits a single result.
I think there is no such singular node in TBB flow graph that does accumulating with some sort of preprocessing and then, when accumulation is done, forwards the result of it to successor.
However, I believe the effect could be achieved by using several nodes. For example, consider queue_node as a starting point in the graph. It will serve as a buffer with FIFO semantics. After it there goes multifunction_node with N outputs. This node will do actual image preprocessing and send the result to its output port that correponds to image number. Then goes join_node that has all its N inputs connected to corresponding outputs of multifunction_node. At the end there will be a successor of join_node that will receive N images as its input. Since join_node aggregates its inputs in a tuple the drawback of this design could be quickly seen in case the number N is relatively large.
The other variant might be having the same queue_node connected with function_node with unlimited concurrency as successor (function_node is supposed to be doing some image preprocessing), and then having a multifunction_node with serial concurrency (meaning that only single instance of its body could be working at a time) that will sort of accumulate the images and do try_put call from inside the body to its successor when the number N is reached.
Of course there could be other variants how to implement desired behavior by using other flow graph topologies. By the way, to make such a graph as a singular node one could use composite_node that represents the subgraphs as a single node.
Related
I have referred quite a lot of materials online, I saw the usage of merge and junction is almost the same? Some sites said to use the diamond shape as a merge, some said to use junction. Can I know which one is correct? The following images are the material I have read.
merge using diamond shape
merge using junction
In a state machine diagram there are two pseudo states that are often confused: The junction state (a black filled circle) and the choice state (a hollow diamond). Don't confuse them with similar shapes in an activity diagram (initial node, decision node and merge node). They only look the same.
Now for the difference between choice and junction states: A compound transition fires, when its triggering event occurs AND all guards before an eventual choice state evaluate to true. Then all the effect behaviors up to the choice state are executed before any of the guards of outgoing transitions are checked. This allows dynamic branching depending on some value that only gets evaluated when the transition has fired.
A junction state just connects transitions. It could be replaced with as many transitions as there are possible routings. Such a transition only fires if all guards on the route evaluate to true.
Both states can have as many in- and outgoing transitions as you like.
As a side note (too long for a comment) the notation for the combined merge/decision needs some clarification. UML 2.5 states on p. 387:
15.3.3.5 Merge Nodes
A MergeNode is a control node that brings together multiple flows without synchronization. A MergeNode shall have exactly one outgoing ActivityEdge but may have multiple incoming ActivityEdges.
and below (a bit more obscure!):
15.3.3.6 Decision Nodes
A DecisionNode is a ControlNode that chooses between outgoing flows. A DecisionNode shall have at least one and at most two incoming ActivityEdges, and at least one outgoing ActivityEdge. If it has two incoming edges, then one shall be identified as the decisionInputFlow, the other being called the primary incoming edge. If the DecisionNode has only one incoming edge, then it is the primary incoming edge.
Note that this is about activities and not states!
As #AxelScheithauer noted, the diagram rendering may deviate. P. 390 of UML 2.5 states
The functionality of a MergeNode and a DecisionNode can be combined by using the same node symbol, as shown in Figure 15.34. At most one of the incoming flows may be annotated as a decisionInputFlow. This notation maps to a model containing a MergeNode with all the incoming edges shown in the diagram and one outgoing edge to a DecisionNode that has all the outgoing edges shown in the diagram.
I have a step function setup which calls preprocessing lambda and inference lambda for a data item. Now, I need to do this process on the entire dataset(over 10000 items). One way is to invoke step function parallelly for each input. Is there a better alternative to this approach?
Another way to do it would be to use Map state to run over an array of items. You could start with a list of item ID's and run a set of tasks for it.
https://aws.amazon.com/blogs/aws/new-step-functions-support-for-dynamic-parallelism/
This approach has some drawbacks though:
There is a 256kb limit for input/output data. The initial array of items could possibly be bigger. If you passes an array of ID's only as an input to map state though, 10k items would likely not cross that limit.
Map state doesn't guarantee that all the items will run concurrently. It could possibly be less than 40 at a time (workaround would be to have nested map states or maps of map states). From documentation:
Concurrent iterations may be limited. When this occurs, some iterations will not begin until previous iterations have completed. The likelihood of this occurring increases when your input array has more than 40 items.
https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-map-state.html
Consider the classic network flow problem where the constraint is that the outflow from a vertex is equal to the sum of the inflows to it. Consider having a more specific constraint where the flow can be split between edges.
I have two questions:
How can I use a decision variable to identify that node j is receiving items from multiple edges?
How to create another equation to determine the cost (2 unit of time per item) of joining x number of items from different edges in the sink node?
This is a tricky modeling question. Let's go by parts.
Consider having a more specific constraint where the flow can be split between edges
I here assume that you have a classic flow constraint modeled as a real variable set y_ij. Therefore, the flow can be split between two or more arcs.
How can I use a decision variable to identify that node j is receiving items from multiple edges?
You need to create an additional binary variable z_ij to represent your flow. You must also create the following constraint:
Next, you will need another additional integer variable set, let's say p_i and an additional constraint
Then, p_i will store the number of ingoing arcs in a node j which are used to send flow. Since you will try to minimize the cost of joining arcs (I think), you need to use the <=.
How to create another equation to determine the cost(2 unit of time per item) of joining x number of items from different edges in the sink node?
For this, you can use the value of p_i and multiply by the predefined cost of joining the flow.
I have a neural network written in standard C++11 which I believe follows the back-propagation algorithm correctly (based on this). If I output the error in each step of the algorithm, however, it seems to oscillate without dampening over time. I've tried removing momentum entirely and choosing a very small learning rate (0.02), but it still oscillates at roughly the same amplitude per network (with each network having a different amplitude within a certain range).
Further, all inputs result in the same output (a problem I found posted here before, although for a different language. The author also mentions that he never got it working.)
The code can be found here.
To summarize how I have implemented the network:
Neurons hold the current weights to the neurons ahead of them, previous changes to those weights, and the sum of all inputs.
Neurons can have their value (sum of all inputs) accessed, or can output the result of passing said value through a given activation function.
NeuronLayers act as Neuron containers and set up the actual connections to the next layer.
NeuronLayers can send the actual outputs to the next layer (instead of pulling from the previous).
FFNeuralNetworks act as containers for NeuronLayers and manage forward-propagation, error calculation, and back-propagation. They can also simply process inputs.
The input layer of an FFNeuralNetwork sends its weighted values (value * weight) to the next layer. Each neuron in each layer afterwards outputs the weighted result of the activation function unless it is a bias, or the layer is the output layer (biases output the weighted value, the output layer simply passes the sum through the activation function).
Have I made a fundamental mistake in the implementation (a misunderstanding of the theory), or is there some simple bug I haven't found yet? If it would be a bug, where might it be?
Why might the error oscillate by the amount it does (around +-(0.2 +- learning rate)) even with a very low learning rate? Why might all the outputs be the same, no matter the input?
I've gone over most of it so much that I might be skipping over something, but I think I may have a plain misunderstanding of the theory.
It turns out I was just staring at the FFNeuralNetwork parts too much and accidentally used the wrong input set to confirm the correctness of the network. It actually does work correctly with the right learning rate, momentum, and number of iterations.
Specifically, in main, I was using inputs instead of a smaller array in to test the outputs of the network.
I’m not specialist in signal processing. I’m doing simple processing on 1D signal using c++. I want really to know how I can determine the part that have the highest zero cross rate (highest frequency!). Is there a simple way or method to tell the beginning and the end of this part.
This image illustrate the form of my signal, and this image is what I need to do (two indexes of beginning and end)
Edited:
Actually I have no prior idea about the width of the beginning and the end, it's so variable.
I could calculate the number of zero crossing, but I have no idea how to define it's range
double calculateZC(vector<double> signals){
int ZC_counter=0;
int size=signals.size();
for (int i=0; i<size-1; i++){
if((signals[i]>=0 && signals[i+1]<0) || (signals[i]<0 && signals[i+1]>=0)){
ZC_counter++;
}
}
return ZC_counter;
}
Here is a fairly simple strategy which might give you some point to start. The outline of the algorithm is as follows
Input: Vector of your data points {y0,y1,...}
Parameters:
Window size sigma.
A threshold 0<p<1 defining when to start looking for a region.
Output: The start- and endpoint {t0,t1} of the region with the most zero-crossings
I won't give any C++ code, but the method should be easy to implement. As example let us use the following function
What we desire is the region between about 480 and 600 where the zero density higher than in the front. First step in the algorithm is to calculate the positions of zeros. You can do this by what you already have but instead of counting, you store the values for i where you met a zero.
This will give you a list of zero positions
From this list (you can do this directly in the above for-loop!) you create a list having the same size as your input data which looks like {0,0,0,...,1,0,..,1,0,..}. Every zero-crossing position in your input data is marked with a 1.
The next step is to smooth this list with a smoothing filter of size sigma. Here, you can use what you like; in the simplest case a moving average or a Gaussian filter. The higher you choose sigma the bigger becomes your look around window which measures how many zero-crossings are around a certain point. Let me give the output of this filter together with the original zero positions. Note that I used a Gaussian filter of size 10 here
In a next step, you go through the filtered data find the maximum value. In this case it is about 0.15. Now you choose your second parameter which is some percentage of this maximum. Lets say p=0.6.
The final step is to go through the filtered data and when the value is greater than p you start to remember a new region. As soon as the value drops below p, you end this region and remember start and endpoint. Once you are finished walking through the data, you are left with a list of regions, each defined by a start and an endpoint. Now you choose the region with the biggest extend and you are done.
(Optionally, you could add the filter size to each end of the final region)
For the above example, I get 11 regions as follows
{{164,173},{196,205},{220,230},{241,252},{259,271},{278,290},
{297,309},{318,327},{341,350},{458,468},{476,590}}
where the one with the biggest extend is the last one {476,590}. The final result looks (with 1/2 filter region padding)
Conclusion
Please don't be discouraged by the length of my answer. I tried to explain everything in detail. The implementation is really just some loops:
one loop to create the zero-crossings list {0,0,..,1,0,...}
one nested loop for the moving average filter (or you use some library Gaussian filter). Here you can at the same time extract the maximum value
one loop to extract all regions
one loop to extract the largest region if you haven't already extracted it in the above step