How to smooth interpolation of a float array into a bigger array? - swift

I'm stuck with interpolation in Swift. Can anyone help me with that?
I want to interpolate the float array (say [0, 0, 100, 25, 0, 0, 0, 25, 0, 0, 0]) into another array with some given size (for example 128). I found an article (Use Linear Interpolation to Construct New Data Points) that shows, how to achieve this stuff.
There are two ways (you can see the results below, how they perform):
Linear Interpolation using vDSP_vgenp and
Smoother (but not for my purposes) Interpolation using vDSP_vlint
The problem is both techniques don't realize my expectations, which illustrated in Screenshot 3. How can I make my interpolated distribution smoother? I want to see a cube-like curve.
Initial Plot:
Linear Interpolation:
import Accelerate
let n = vDSP_Length(128)
let stride = vDSP_Stride(1)
let values: [Float] = [0, 0, 100, 25, 0, 0, 0, 25, 0, 0, 0]
let indices: [Float] = [0, 11, 23, 34, 46, 58, 69, 81, 93, 104, 116]
var result = [Float](repeating: 0, count: Int(n))
vDSP_vgenp(values, stride, indices, stride, &result, stride, n, vDSP_Length(values.count))
Smooth Interpolation:
import Accelerate
import AVFoundation
let n = vDSP_Length(1024)
let stride = vDSP_Stride(1)
let values: [Float] = [0, 0, 100, 25, 0, 0, 0, 25, 0, 0, 0]
let denominator = Float(n) / Float(values.count - 1)
let control: [Float] = (0 ... n).map {
let x = Float($0) / denominator
return floor(x) + simd_smoothstep(0, 1, simd_fract(x))
}
var result = [Float](repeating: 0, count: Int(n))
vDSP_vlint(values, control, stride, &result, stride, n, vDSP_Length(values.count))

It seems to me that the vDSP_vqint quadratic interpolation functions would solve the problem. See the discussion at https://developer.apple.com/documentation/accelerate/1449942-vdsp_vqint.

Related

LAPack dpbsv returns 3 for positive definite matrix

I am trying to use the LAPACK banded symmetric matrix solver dpbsv. I am testing the matrix:
4, 2, 0, 0, 0
2 4, 3, 0, 0
0, 3, 11, 7, 0
0, 0, 7, 11, 5
0, 0, 0, 5, 13
Mathematica tells me that this matrix is positive definite, with a determinate of 3684
I am using swift and have constructed the array
var a: [Double] = [ 0, 2, 3, 7, 5,
4, 4, 11, 11, 13]
var b: [Double] = [1, 2, 3, 4, 5]
And I am calling dpbsv as
var uplo = Int8("U".utf8.first!) // set to 'U'
var n = __CLPK_integer(5)
var kd = __CLPK_integer(1)
var ldab = kd + 1
var nrhs = __CLPK_integer(1)
var ldb = __CLPK_integer(5)
var info: __CLPK_integer = 0
dpbsv_(&uplo,
&n,
&kd,
&nrhs,
&a,
&ldab,
&b,
&ldb,
&info)
if info != 0 {
// here info is 3, indicating non-positive definite.
NSLog("error \(info)")
}
Any idea what the issue is here? Am I interpreting the parameters to dpbsv_ correctly? I've tried other matrices that Mathematica claims are pos-def with the same result.
So, apparently, what LAPACK documents as rows need to be coded as columns in swift. So, if the array is changed to
[ 0, 4,
2, 4,
3, 11,
7, 11,
5, 13]
everything works fine.

Dimension out of range (expected to be in range of [-1, 0], but got 1) (pytorch)

I have a very simple feed forward neural network (pytorch)
import torch
import torch.nn.functional as F
import numpy as np
class Net_1(nn.Module):
def __init__(self):
super(Net_1, self).__init__()
self.fc1 = nn.Linear(5*5, 64)
self.fc2 = nn.Linear(64, 32)
self.fc3 = nn.Linear(32, 3)
def forward(self,x):
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return F.log_softmax(x, dim=1)
net = Net_1()
and the input is this 5x5 numpy array
state = [[0, 0, 3, 0, 0],
[0, 0, 0, 0, 0],
[0, 2, 1, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]]
state = torch.Tensor(state).view(-1)
net(state) throws the following error
Dimension out of range (expected to be in range of [-1, 0], but got 1)
the problem is when F.log_softmax() is applied
at the point when you call return F.log_softmax(x, dim=1), x is a 1-dimensional tensor with shape torch.Size([3]).
dimension indexing in pytorch starts at 0, so you cannot use dim=1 for a 1-dimensional tensor, you will need to use dim=0.
replace return F.log_softmax(x, dim=1) with return F.log_softmax(x, dim=0) and you'll be good to go.
in the future you can check tensor sizes by adding print(x.shape) in forward.
You are giving a 3 element 1d array to your log_softmax function.
When saying dim=1 you are telling it to apply softmax to an axis that doesn't exist.
Just set dim=0 for a 1d array.
More on this function and what that parameter means here

Why do I need to initialize the struct with self.init() even if I assign all of the properties?

In simd_float4x4, columns is the only property, however, this won't work solely because I'm not calling self.init(). Everything would have been initialize anyway. Why is the compiler complaining? I saw something similar in this video, and it was working. Why can't I do it?
extension simd_float4x4 {
init(ProjectionFrame: CGSize) {
let Y = FOV(), FarZ = Float((Settings.VisibilityRange+1)*2), Z = FarZ / (NearZ - FarZ)
columns = (vector_float4(Y / Float(ProjectionFrame.width / ProjectionFrame.height), 0, 0, 0), vector_float4(0, Y, 0, 0), vector_float4(0, 0, Z, -1), vector_float4(0, 0, Z * NearZ, 0))
}
}
In the video I noticed this.
extension simd_float4x4 {
init(translationX x: Float, x: Float, x: Float) {
columns = (
vector_float4(x, 0, 0, 0),
vector_float4(0, x, 0, 0),
vector_float4(0, 0, x, 0),
vector_float4(0, 0, 0, 1)
)
}
}
And the compiler wasn't complaining. How come it's complaining for me?
Instead of trying to set columns from your init, you should just call self.init(_ columns:) and pass in the 4 vector_float4s as an Array rather than as a tuple.
extension simd_float4x4 {
init(ProjectionFrame: CGSize) {
let Y = FOV(), FarZ = Float((Settings.VisibilityRange+1)*2), Z = FarZ / (NearZ - FarZ)
self.init([vector_float4(Y / Float(ProjectionFrame.width / ProjectionFrame.height), 0, 0, 0), vector_float4(0, Y, 0, 0), vector_float4(0, 0, Z, -1), vector_float4(0, 0, Z * NearZ, 0)])
}
}
That video is 2 years old and hence uses an older Swift version. The code you link from that video also doesn't compile in Swift 5.
Unrelated to your question, but variable names in Swift should be lowerCamelCase, so projectionFrame is the correct naming.
Alternatively I could bridge it to C
#include <simd/simd.h>
matrix_float4x4 ProjectPerspective(const float Ratio) {
const float Y = 1/tanf(Rad(Settings.FOV+15)), FarZ = (Settings.VisibilityRange+1)*32, Z = FarZ/(NearZ-FarZ);
return (matrix_float4x4){.columns = {{Y/Ratio, 0, 0, 0}, {0, Y, 0, 0}, {0, 0, Z, -1}, {0, 0, Z*NearZ, 0}}};
}

How to construct a sobel filter for kernel initialization in input layer for images of size 128x128x3?

This is my code for sobel filter:
def init_f(shape, dtype=None):
sobel_x = tf.constant([[-5, -4, 0, 4, 5], [-8, -10, 0, 10, 8], [-10, -20, 0, 20, 10], [-8, -10, 0, 10, 8], [-5, -4, 0, 4, 5]])
ker = np.zeros(shape, dtype)
ker_shape = tf.shape(ker)
kernel = tf.tile(sobel_x, ker_shape)//*Is this correct?*
return kernel
model.add(Conv2D(filters=30, kernel_size=(5,5), kernel_initializer=init_f, strides=(1,1), activation='relu'))
So far I have managed to do this.
But, this gives me error:
Shape must be rank 2 but is rank 4 for 'conv2d_17/Tile' (op: 'Tile') with input shapes: [5,5], [4].
Tensorflow Version: 2.1.0
You're close, but the args to tile don't appear to be correct. That is why you're getting the error "Shape must be rank 2 but is rank 4 for..." You're sobel_x must be a rank 4 tensor, so you need to add two more dimensions. I used reshape in this example.
from tensorflow import keras
import tensorflow as tf
import numpy
def kernelInitializer(shape, dtype=None):
print(shape)
sobel_x = tf.constant(
[
[-5, -4, 0, 4, 5],
[-8, -10, 0, 10, 8],
[-10, -20, 0, 20, 10],
[-8, -10, 0, 10, 8],
[-5, -4, 0, 4, 5]
], dtype=dtype )
#create the missing dims.
sobel_x = tf.reshape(sobel_x, (5, 5, 1, 1))
print(tf.shape(sobel_x))
#tile the last 2 axis to get the expected dims.
sobel_x = tf.tile(sobel_x, (1, 1, shape[-2],shape[-1]))
print(tf.shape(sobel_x))
return sobel_x
x1 = keras.layers.Input((128, 128, 3))
cvl = keras.layers.Conv2D(30, kernel_size=(5,5), kernel_initializer=kernelInitializer, strides=(2,2), activation='relu')
model = keras.Sequential();
model.add(x1)
model.add(cvl)
data = numpy.ones((1, 128, 128, 3))
data[:, 0:64, 0:64, :] = 0
pd = model.predict(data)
print(pd.shape)
d = pd[0, :, :, 0]
for row in d:
for col in row:
m = '0'
if col != 0:
m = 'X'
print(m, end="")
print("")
I looked at using expand_dims instead of reshape but there didn't appear any advantage. broadcast_to seems ideal, but you still have to add the dimensions, so I don't think it was better than tile.
Why 30 filters of the same filter though? Are they going to be changed afterwards?

How to generate vector with different prob. distributions for each element

I need to generate vector r of N values 1-6 (they can be repetitive) to given permutation p of N elements. But the values are generated with some probability distribution depending on the i-th value of the permutation.
E.g. I have permutation p = [2 3 1 4] and probabilistic distribution matrix (Nx6): Pr = [1, 0, 0, 0, 0, 0; 0, 0.5, 0, 0.5, 0, 0; 0, 0, 0, 1, 0, 0; 0.2, 0.2, 0.2, 0.2, 0.2, 0]
i-th row represents prob. distribution of values 1-6 to element i in permutation p (its value, not position), sum of rows is 1.
For example, we can assign value 1 to value 1, value 2 or 4 to value 2 etc. So it can look like this: r = [2 4 1 2] or r = [4 4 1 5].
Currently I am using this code:
for i = 1:N
r(i) = randsample(1:6,1,true,Pr(p(i),:));
end
But it is quite slow and I am trying to avoid the for-cycle, maybe by function bsxfun or something similar.
Does anyone have any clue, please? :-)
A solution to your problem is basically available in this answer, everything needed for your case is replacing the vector prob with a matrix and fix all operations to work properly on matrices.
Pr=[1, 0, 0, 0, 0, 0; 0, 0.5, 0, 0.5, 0, 0; 0, 0, 0, 1, 0, 0; 0.2, 0.2, 0.2, 0.2, 0.2, 0];
p = [2 3 1 4];
prob=Pr(p,:);
r=rand(size(pPr,1),1);
x=sum(bsxfun(#ge,r,cumsum(padarray(prob,[0,1],'pre'),2)),2);