Related
I have 3 arrays down below a and b combine to make a_and_b. a is multiplied by a_multiplier and b gets multiplied by b_multiplier. How would I be able to modify a_and_b after the multiplier has been implemented in it.
Code:
import numpy as np
a_multiplier = 3
b_multiplier = 5
a = np.array([5,32,1,4])
b = np.array([1,5,11,3])
a_and_b = np.array([5,1,32,5,1,11,4,3])
Expected Output:
[15, 5, 96, 25, 3, 55, 12, 15]
first learn how to use the multiply:
In [187]: a = np.array([5,32,1,4])
In [188]: a*3
Out[188]: array([15, 96, 3, 12])
In [189]: b = np.array([1,5,11,3])
In [190]: b*5
Out[190]: array([ 5, 25, 55, 15])
One way to combine the 2 arrays:
In [191]: np.stack((a*3, b*5),axis=1)
Out[191]:
array([[15, 5],
[96, 25],
[ 3, 55],
[12, 15]])
which can be easily turned into the desired 1d array:
In [192]: np.stack((a*3, b*5),axis=1).ravel()
Out[192]: array([15, 5, 96, 25, 3, 55, 12, 15])
I have two arrays of same length
import scala.util.Random
val length = 10
val x = 60 // Selection percentage
val rnd = new Random
var arrayOne = Array.fill(length)(rnd .nextInt(100))
arrayOne: Array[Int] = Array(8, 77, 11, 19, 17, 73, 5, 18, 45, 69)
val arrayTwo = Array.fill(length)(rnd .nextInt(100))
arrayTwo: Array[Int] = Array(96, 21, 85, 70, 28, 5, 31, 56, 27, 76)
I can select first x percent element from arrayTwo and those selected elements can replace first x percent elements of arrayOne in the following way.
arrayOne = arrayTwo.take((length * x / 100).toInt) ++ arrayOne.drop((length * x / 100).toInt)
arrayOne: Array[Int] = Array(96, 21, 85, 70, 28, 5, 5, 18, 45, 69)
Now I want to select random x percent elements from arrayTwo and that selected elements will replace random x percent elements of arrayOne. How can I do this?
You can exchange every item with a probability x:
val x = 60D
val exchanged = arrayOne.indices
.map(x => if(math.random > x / 100) arrayOne(x) else arrayTwo(x))
But that way you have no guarantee that (length * x / 100).toInt elements will be from arrayTwo. To achieve that I would go for iterative / recursive algorithm, where I'd pick random index until I have as much as I want.
You can do it via Random.shuffle:
scala> val randSet = Random.shuffle(arrayOne.indices.toBuffer).take((arrayOne.length * x / 100).toInt).toSet
randSet: scala.collection.immutable.Set[Int] = HashSet(0, 6, 9, 3, 8, 4)
scala> val randMerged = arrayOne.indices.map(i => if(randSet(i)) arrayTwo(i) else arrayOne(i))
randMerged: IndexedSeq[Int] = Vector(96, 77, 11, 70, 28, 73, 31, 18, 27, 76)
The randSet will take x percent indices randomly.
If you do not care the number's position, there is a simple one:
scala> val size = (arrayOne.length * x / 100).toInt
size: Int = 6
scala> Random.shuffle(arrayTwo).take(size) ++ Random.shuffle(arrayOne).drop(size)
res11: scala.collection.mutable.ArraySeq[Int] = ArraySeq(76, 85, 28, 56, 21, 27, 69, 45, 17, 77)
Given Scala arrayBuffer:
ArrayBuffer(200, 13, 1, 200, 15, 1, 201, 13, 0, 202, 14, 3, 199, 10, 2, 199, 11, 3, 199, 96, 2)
Expected output:
ArrayBuffer((200, 13, 1), (200, 15, 1), (201, 13, 0), (202, 14, 3), (199, 10, 2), (199, 11, 3), (199, 96, 2))
Is there any simple way of achieving this form of chunking in Scala without for loops? The required chunk_size is 3. And the order of these elements must be the same.
I've tried:
def chunkArray(myArray){
val chunk_size = 3
var index = 0
var arrayLength = arrayToInsert.length
var tempArray = ArrayBuffer[Int](2)
val numChunks = arrayToInsert.length / 3
for (i <- 0 to numChunks-1) {
var myChunk = arrayToInsert.slice(i*chunk_size, (i+1)*chunk_size)
tempArray += (myChunk(0), myChunk(1), myChunk(2))
}
}
Expected result:
((200, 13, 1), (200, 15, 1), (201, 13, 0), (202, 14, 3), (199, 10, 2), (199, 11, 3), (199, 96, 2))
You want to use .grouped(3)
( the collections API examples )
collection.mutable.ArrayBuffer(200, 13, 1, 200, 15, 1, 201, 13, 0, 202, 14, 3, 199, 10, 2, 199, 11, 3, 199, 96, 2).grouped(3).toArray
res2: Array[collection.mutable.ArrayBuffer[Int]] = Array(ArrayBuffer(200, 13, 1), ArrayBuffer(200, 15, 1), ArrayBuffer(201, 13, 0), ArrayBuffer(202, 14, 3), ArrayBuffer(199, 10, 2), ArrayBuffer(199, 11, 3), ArrayBuffer(199, 96, 2))
This will create a Buffer of tuples, which is what the original code appears to attempt.
import collection.mutable.ArrayBuffer
val data =
ArrayBuffer(200, 13, 1, 200, 15, 1, 201, 13, 0 /*etc.*/)
data.grouped(3).collect{case Seq(a,b,c) => (a,b,c)}.toBuffer
//res0: Buffer[(Int, Int, Int)] = ArrayBuffer((200,13,1), (200,15,1), (201,13,0) /*etc.*/)
Note that if the final group is not 3 elements then it will be ignored.
This could also be achieved using sliding:
myArray.sliding(3, 3).toArray
Anyway, .grouped is better suited for this use case as discussed here Scala: sliding(N,N) vs grouped(N)
i have a numpy array r when i used to create another array r2 out of it and turning that new array r2 to zero it also changed the original array r
I have searched around the similar questions but did not turned around the any satisfying answer for this, so please consider suggesting an appropriate answer.
Original Array:
>>> r
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23],
[24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35]])
another numpy array from original array r2 as follows:
>>> r2 = r[:3, :3]
>>> r2
array([[ 0, 1, 2],
[ 6, 7, 8],
[12, 13, 14]])
So, When i do set new array to r2 to zero
>>> r2[:] = 0
>>> r2
array([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
So, when i see original array then it also been looked change:
Array Changed after chanin the new array:
>>> r
array([[ 0, 0, 0, 3, 4, 5],
[ 0, 0, 0, 9, 10, 11],
[ 0, 0, 0, 15, 16, 17],
[18, 19, 20, 21, 22, 23],
[24, 25, 26, 27, 28, 29],
[30, 30, 30, 30, 30, 30]])
Happy New Years in advanced, Guys!
Explanation
r2 = r[:3, :3]
Doesn't create a new array, but renames the current array. What you need to do is known as 'deep copy'. Use, numpy.copy() to do what you need.
x = np.array([1, 2, 3])
y = x
z = np.copy(x)
x[0] = 10
x[0] == y[0]
True
x[0] == z[0]
False
Read more from,
https://het.as.utexas.edu/HET/Software/Numpy/reference/generated/numpy.copy.html
I have 100 3x3x3 matrices that I would like to multiply with another large matrix of size 3x5x5 (similar to convolving one image with multiple filters, but not quite).
For the sake of explanation, this is what my large matrix looks like:
>>> x = np.arange(75).reshape(3, 5, 5)
>>> x
array([[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]],
[[25, 26, 27, 28, 29],
[30, 31, 32, 33, 34],
[35, 36, 37, 38, 39],
[40, 41, 42, 43, 44],
[45, 46, 47, 48, 49]],
[[50, 51, 52, 53, 54],
[55, 56, 57, 58, 59],
[60, 61, 62, 63, 64],
[65, 66, 67, 68, 69],
[70, 71, 72, 73, 74]]])
In memory, I assume all sub matrices in the large matrix are stored in contiguous locations (please correct me if I'm wrong). What I want to do is, from this 3x5x5 matrix, I want to extract 3 5x3 columns from each sub-matrix of the large matrix and then join them horizontally to get a 5x9 matrix (I apologise if this part is not clear, I can explain in more detail if need be). If I were using numpy, I'd do:
>>> k = np.hstack(np.vstack(x)[:, 0:3].reshape(3, 5, 3))
>>> k
array([[ 0, 1, 2, 25, 26, 27, 50, 51, 52],
[ 5, 6, 7, 30, 31, 32, 55, 56, 57],
[10, 11, 12, 35, 36, 37, 60, 61, 62],
[15, 16, 17, 40, 41, 42, 65, 66, 67],
[20, 21, 22, 45, 46, 47, 70, 71, 72]])
However, I'm not using python so I do not have any access to the numpy functions that I need in order to reshape the data blocks into a form I want to carry out multiplication... I can only directly call the cblas_sgemm function (from the BLAS library) in C, where k corresponds to input B.
Here's my call to cblas_sgemm:
cblas_sgemm( CblasRowMajor, CblasNoTrans, CblasTrans,
100, 5, 9,
1.0,
A, 9,
B, 9, // this is actually wrong, since I don't know how to specify the right parameter
0.0,
result, 5);
Basically, the ldb attribute is the offender here, because my data is not blocked the way I need it to be. I have tried different things, but I am not able to get cblas_sgemm to understand how I want it to read and understand my data.
In short, I don't know how to tell cblas_sgemm to read x like k.Is there a way I can smartly reshape my data in python before sending it to C, so that cblas_sgemm can work the way I want it to?
I will transpose k by setting CblasTrans, so during multiplication, B is 9x5. My matrix A is of shape 100x9. Hope that helps.
Any help would be appreciated. Thanks!
In short, I don't know how to tell cblas_sgemm to read x like k.
You can't. You'll have to make a copy.
Consider k:
In [20]: k
Out[20]:
array([[ 0, 1, 2, 25, 26, 27, 50, 51, 52],
[ 5, 6, 7, 30, 31, 32, 55, 56, 57],
[10, 11, 12, 35, 36, 37, 60, 61, 62],
[15, 16, 17, 40, 41, 42, 65, 66, 67],
[20, 21, 22, 45, 46, 47, 70, 71, 72]])
In a two-dimensional array, the spacing of the elements in memory must be the same in each axis. You know from how x was created that the consecutive elements in memory are 0, 1, 2, 3, 4, ..., but your first row of k contains 0, 1, 2, 25, 26, ..... The is no spacing between 1 and 2 (i.e. the memory address increases by the size of one element of the array), but there is a large jump in memory between 2 and 25. So you'll have to make a copy to create k.
Having said that, there is an alternative method to efficiently achieve your desired final result using a bit of reshaping (without copying) and numpy's einsum function.
Here's an example. First define x and A:
In [52]: x = np.arange(75).reshape(3, 5, 5)
In [53]: A = np.arange(90).reshape(10, 9)
Here's my understanding of what you want to achieve; A.dot(k.T) is the desired result:
In [54]: k = np.hstack(np.vstack(x)[:, 0:3].reshape(3, 5, 3))
In [55]: A.dot(k.T)
Out[55]:
array([[ 1392, 1572, 1752, 1932, 2112],
[ 3498, 4083, 4668, 5253, 5838],
[ 5604, 6594, 7584, 8574, 9564],
[ 7710, 9105, 10500, 11895, 13290],
[ 9816, 11616, 13416, 15216, 17016],
[11922, 14127, 16332, 18537, 20742],
[14028, 16638, 19248, 21858, 24468],
[16134, 19149, 22164, 25179, 28194],
[18240, 21660, 25080, 28500, 31920],
[20346, 24171, 27996, 31821, 35646]])
Here's how you can get the same result by slicing x and reshaping A:
In [56]: x2 = x[:,:,:3]
In [57]: A2 = A.reshape(-1, 3, 3)
In [58]: einsum('ijk,jlk', A2, x2)
Out[58]:
array([[ 1392, 1572, 1752, 1932, 2112],
[ 3498, 4083, 4668, 5253, 5838],
[ 5604, 6594, 7584, 8574, 9564],
[ 7710, 9105, 10500, 11895, 13290],
[ 9816, 11616, 13416, 15216, 17016],
[11922, 14127, 16332, 18537, 20742],
[14028, 16638, 19248, 21858, 24468],
[16134, 19149, 22164, 25179, 28194],
[18240, 21660, 25080, 28500, 31920],
[20346, 24171, 27996, 31821, 35646]])