Related
I would like to execute the equivalent of the following MATLAB code using NumPy: repmat([1; 1], [1 1 1]). How would I accomplish this?
Here is a much better (official) NumPy for Matlab Users link - I'm afraid the mathesaurus one is quite out of date.
The numpy equivalent of repmat(a, m, n) is tile(a, (m, n)).
This works with multiple dimensions and gives a similar result to matlab. (Numpy gives a 3d output array as you would expect - matlab for some reason gives 2d output - but the content is the same).
Matlab:
>> repmat([1;1],[1,1,1])
ans =
1
1
Python:
In [46]: a = np.array([[1],[1]])
In [47]: np.tile(a, [1,1,1])
Out[47]:
array([[[1],
[1]]])
Note that some of the reasons you'd need to use MATLAB's repmat are taken care of by NumPy's broadcasting mechanism, which allows you to do various types of math with arrays of similar shape. So if you had, say, a 1600x1400x3 array representing a 3-color image, you could (elementwise) multiply it by [1.0 0.25 0.25] to reduce the amount of green and blue at each pixel. See the above link for more information.
This is how I understood it out of a bit of fiddling around. Happy to be corrected and hope this helps.
Say you have a matrix M of 2x3 elements. This has two dimensions, obviously.
I could see no difference between Matlab and Python while asking to manipulate the input matrix along the dimensions the matrix already has.
Thus the two commands
repmat(M,m,n) % matlab
np.tile(M,(m,n)) # python
are really equivalent for a matrix of rank 2 (two dimensions).
The matters goes counter-intuitive when you ask for repetition/tiling over more dimensions than the input matrix has. Going back to the matrix M of rank two and shape 2x3, it is sufficient to look at what happens to the size/shape of the output matrix. Say the sequence for manipulation is now 1,1,2.
In Matlab
> size(repmat(M,1,1,2))
ans =
2 3 2
it has copied the first two dimensions (rows and columns) of the input matrix and has repeated that once into a new third dimension (copied twice, that is). True to the naming repmat for repeat matrix.
In Python
>>> np.tile(M,(1,1,2)).shape
(1, 2, 6)
it has applied a different procedure since, I presume, the sequence (1,1,2) is read differently than in Matlab. The number of copies in the direction of columns, rows and out-of-plane dimension are being read from right to left. The resulting object has a different shape from Matlab. One can no longer assert that repmat and tile are equivalent instructions.
In order to get tile to behave like repmat, in Python one has to make sure that the input matrix has as many dimensions as the elements are in the sequence. This is done, for example, by a little preconditioning and creating a related object N
N = M[:,:,np.newaxis]
Then, at the input side one has N.shape = (2,3,1) rather than M.shape = (2,3) and at the output side
>>> np.tile(N,(1,1,2)).shape
(2, 3, 2)
which was the answer of size(repmat(M,1,1,2)). I presume this is because we have guided Python to add the third dimension to the right of (2,3) rather than to its left, so that Python works out the sequence (1,1,2) as it was intended in the Matlab way of reading it.
The element in [:,:,0] in the Python answer for N will contain the same values as the element (:,:,1) the Matlab answer for M.
Finally, I can't seem to find an equivalent for repmat when one uses the Kronecker product out of
>>> np.kron(np.ones((1,1,2)),M).shape
(1, 2, 6)
unless I then precondition M into N as above. So I would argue that the most general way to move on is to use the ways of np.newaxis.
The game gets trickier when we consider a matrix L of rank 3 (three dimensions) and the simple case of no new dimensions being added in the output matrix. These two seemingly equivalent instructions will not produce the same results
repmat(L,p,q,r) % matlab
np.tile(L,(p,q,r)) # python
because the row, column, out-of-plane directions are (p,q,r) in Matlab and (q,r,p) in Python, which was not visible with rank-2 arrays. There, one has to be careful and obtaining the same results with the two languages would require more preconditioning.
I am aware that this reasoning may well not be general, but I could work it out only this far. Hopefully this invites other fellows to put it to a harder test.
See NumPy for Matlab users.
Matlab:
repmat(a, 2, 3)
Numpy:
numpy.kron(numpy.ones((2,3)), a)
Matlib in Numpy (numpy.matlib.repmat()):
numpy.matlib.repmat(a, 2, 3)
Know both tile and repeat.
x = numpy.arange(5)
print numpy.tile(x, 2)
print x.repeat(2)
numpy.matlib has a repmat function with a similar interface as the matlab function
from numpy.matlib import repmat
repmat( np.array([[1],[1]]) , 1, 1)
>>> import numpy as np
>>> np.repeat(['a','b'], [2,5])
array(['a', 'a', 'b', 'b', 'b', 'b', 'b'], dtype='<U1')
>>> np.repeat([1,2], [2,5])
array([1, 1, 2, 2, 2, 2, 2])
>>> np.repeat(np.array([1,2]), [3]).reshape(2,3)
array([[1, 1, 1],
[2, 2, 2]])
>>> np.repeat(np.array([1,2]), [2,4]).reshape(3,2)
array([[1, 1],
[2, 2],
[2, 2]])
>>> np.repeat(np.matrix('1 2; 3 4'), [2]).reshape(4,2)
matrix([[1, 1],
[2, 2],
[3, 3],
[4, 4]])
I'm not sure if this question belongs on stackoverflow or math, but I'll give stackoverflow a shot.
I'm attempting to create an algorithm / function that will allow me to solve a puzzle, but I am simply unable to. The puzzle is as stated.
Let a unit be a function that accepts a integer i between 0 and 15.
A unit can add or subtract any number in the range 0 - 15 to/from i.
Additionally, instead of adding or subtracting a number to/from i, a unit can also contain a number from 0-15 and subtract i from that.
A unit can only perform 2 operations on a number, and the operation producing the largest value will be the output of the unit.
Values only go from 0 - 15, so 9 - 15 = 0 and 13 + 5 = 15.
We may combine units together to produce a more complex result.
The first unit may only accept numbers ranging from 0 - 9.
In my examples I will string together 3 units.
This is a problem that is unrelated to coding, but it seems that I need a program to figure out possible solutions. I've attempted to create a brute force algorithm to find solutions, but I've been unable to do so, as I'm not that great with coding.
For example, a problem could be:
For values 1 and 4, let the output be 0. For all others, e.g. 0, 2, 3, 5, 6, 7, 8, 9, the output must be greater than 0.
A solution here might be:
def unit1(input):
return max(5 - input, input)
def unit2(input):
max(14 - input, input)
def unit3(input):
max(10 - input, input - 10)
print(unit3(unit2(unit1(4))))
Another example might be:
For values 4, 5, 6 and 8 the output must be 3 or greater. For all others, e.g. 0, 1, 2, 3, 7, 9, the output must be less than 3.
A solution here might be:
def unit1(input):
return max(4 - input, input - 4)
def unit2(input):
max(2, input)
def unit3(input):
max(1 - input, input - 6)
print(unit3(unit2(unit1(5))))
Given an example as the two stated above, is there a general algorithm / formula I can use to find my desired output?
Additionally, is it possible to solve the problems above using only 2 units?
Please do let me know if I need to elaborate on something, and know that your help is extremely appreciated!
There seems to be basically two kinds of things you have to do: map inputs that should be handled the same way to contiguous ranges, and then move contiguous ranges to the right place.
max(A-x,x-B) is the only kind of unit that can map non-contiguous ranges together. It has limitations: It always maps 2 inputs onto one output, and you've gotta be careful never to map two inputs that have to be handled differently onto the same output.
In terms of what gets mapped together, you only need one parameter, since max(x,A-x) handles all cases. You can try all 16 possibilities to see if any of them help. Sometimes you may need to do a saturating add before the max to collapse inputs at the top or bottom of the range.
In your first example, you need to map 0 and 4 together.
In max(x,A-x), we need 4 = A-1.
Solving that we get A=5, so we start with
max(x, 5-x)
That maps 4 and 1 to 4, and everything else to other values.
Now we need to combine the ranges above and below 4. Everything less than 4 has to map to something higher than 4. We solve 5 = A-3 to get A = 8:
max(x, 8-x)
Now the ranges of things that need to be handled the same way are contiguous, so we just need to move them to the right place. We have values >=4 and we need 4->0. We could add a subtraction unit, but it's shorter just to shift the previous max by subtracting 4 from both cases. We're left with a final solution
max(x, 5-x)
max(x-4, 4-x)
You haven't really defined all the possible questions you might be asked, but it looks like they can all be solved by this two step combine-and-shift process. Sometimes there will be no solution because you can't combine ranges in any valid way with max.
I think your missing piece you need to proceed is a higher-order function. That's a function that returns another function. Something like:
def createUnit(sub, add):
def unit(input):
return max(sub - input, input + add)
return unit
You can use it like:
unit1 = createUnit(5, 0)
unit2 = createUnit(14, 0)
unit3 = createUnit(10, -10)
Your first example can be solved with two units, but your second example can't.
I think the key to solving this efficiently is to work backwards from the output to the input, but I haven't spent enough time on it to figure out precisely how to do so.
I implemented some code with tf.tile and got this error message:
InvalidArgumentError : expected multiples argument to be a vector of length 2 but got length 3
The code is quite complicated and I can't directly find out what caused the error. So I made some dummy codes to reproduce the error, so that I may understand which value was the source of the error. However, I can't figure out how to reproduce this error with dummy code.
I tried to do it like this:
import tensorflow as tf
a = tf.constant([[1,2,3],[2,3,4]])
b = tf.tile(a, [1,1,3])
This gives me error the message:
Shape must be rank 2 but is rank 3 for 'Tile_0' with input shapes:~~
Can anybody provide some example code that can reproduce my original error?
After four years, I suspect a direct solution won't be useful, so here's a general explanation for the other 2,000 people that have viewed this in the meantime!
From the documentation:
This operation creates a new tensor by replicating input multiples times. The output tensor's i'th dimension has input.dims(i) * multiples[i] elements, and the values of input are replicated multiples[i] times along the 'i'th dimension. For example, tiling [a b c d] by [2] produces [a b c d a b c d].
Your a vector is a rank-2 tensor, so tf.tiles expects multiples to have 2 elements, but your multiples has 3 elements. You must match a's dimension with the length of multiples.
I have an 1D array of weights, w and an array of capacities c of the same shape as w. I need to find the smallest array of indices such that when w is split by these indices, the cumsums of split arrays less than the corresponding capacities in c.
Given an array of weights and capacities as follows:
w = [1,2,3,4,5,6]; c = [3, 12, 7, 6, 12]
I need to find the smallest number of indices 'i' so that the cumsums of split arrays less than the corresponding capacities in c. In this case,
i = [2, 3, 5]
The cumsums of split arrays of w formed by i are
[1, 1+2, 1+2+3, 4, 5, 5+6]
each element is clearly less than c. The cum sums are calculated as given here.
An approximation of the required indices is also fine. But the cumsums should be strictly less than corresponding elements in c.
w is a very large array (size 100000 elements). I need a vectorized solution for it to be efficient. As said before, approximations are fine as long as the cumsums are less than c
Here is what I've tried. I've assumed that the entire c matrix is just one element repeated multiple times (I'm trying to solve a simpler case first and then add complexities). In this case, I just have to ensure that each split array has to have sum less than a given value (somewhat similar to bin packing). I find the indices as follows.
weights = np.random.random_integers(1, 20, size=(20))
capacity = 100
# Find cumulative sums and divide by capacity. This gives an approximation of indices. All elements in first
# split array would have values between 0 and 1. Those in second array would have elements between 1 and 2,
# and so on. When ever the integer part changes, a new split array would be formed. Find indices from this.
# After taking the ceiling value of all elements, elements between 0 and 1 would become 1, elements between
# 1 and 2 become 2 and so on. The place where the elements change give the indices. Take diff to find the
# boundary (of change).
indices = np.diff(np.ceil(np.cumsum(weights[i]) / self.sleigh_capacity))
# 0s represent repeated elements, 1s represent values where values change. Find the indices
indices = np.where(indices != 0)[0] + 1
This gives me the indices. One thing to note is that this might give me wrong indices, because cumulative sums are calculated from the beginning.
That is, cumsum of [1,2,3,2,3] is [1,2,6,8,9]. Now if my capacity is 5.
dividing cumsum by 5 and taking ceil gives me [1, 1, 2, 2, 2] which would correspond to splitting indices of [1, 4]. But the actual splitting indices are [1, 3, 4]. I'm handling this by reducing the capacity. That is, if my actual capacity is 5, I'd take it as 4 and then do the above (The value 4 is gotten by pure guess. To be on the safer side I might decrease the capacity even further).
But I'm not able to extend this method to the case where the capacities are varying. That is, if I have a capacity array of shape (1,5) then I would have to use a different approach, as this approach wouldn't work.
w = [1,2,3,1,6,6]; c = [1,3,5, 1, 6, 12]
The only solution to this is
i=[2,3,4,5]
The greedy solution (to my understanding is to take until you cannot take)
It starts off with a 2 to get the [1,2] < =[1, 1+2] in c.
However, if the next split is at 4 (as the greedy solution leads to, you get into issues since nothing can satisfy the 1). We should have instead split it at 2 and 3.
I suggested using backtracking to look back when this happens, but the running time could spiral out of control. The limit with 100k seems to suggest a linear solution or nlogn solution at worst. I have ideas of how to do this with dynamic programming, but still figuring out some specifics. Will update hopefully, or discard answer after a while. :)
I have a set of tasks i have to complete please help me im stuck on the multiplication one :(
1. np.array([0,5,10]) will create an array of integers starting at 0, finishing at 10, with step 5. Use a different command to create the same array automatically.
array_a = np.linspace(0,10,5)
print array_a
Is this correct? Also what is meant by automatically?
2. Create (automatically, not using np.array!) another array that contains 3 equally-spaced floating point numbers starting at 2.5 and finishing at 3.5.
array_b = np.linspace(2.5,3.5,3,)
print array_b
Use the multiplication operator * to multiply the two arrays together
How do i multiply them? I get an error that they arent the same shape, so do i need to slice array a?
The answer to the first problem is wrong; it asks you to create an array with elements [0, 5, 10]. When I run your code it prints [ 0. , 2.5, 5. , 7.5, 10. ] instead. I don't want to give the answer away completely (it is homework after all), but try looking up the docs for the arange function. You can solve #1 with either linspace or arange (you'll have to tweak the parameters either way), but I think the arange function is more suited to the specific wording of the question.
Once you've got #1 returning the correct result, the error in #3 should go away because the arrays will both have length 3 (i.e. they'll have the same shape).