Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 months ago.
Improve this question
I have been using Curve Fitting app but canĀ“t find a way to make a fatorial fit in it. Any ideias of how to perform a fatorial fit in my data?
x = [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];
y = [20, 30, 42, 56, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 28800, 36992, 46818, 58482, 72200, 88200, 106722, 128018, 1068672, 1322500, 1622400, 1974375, 2384928, 2861082, 3410400];
I will not help you about "fatorial fit" as you probably wrote it incorrectly.
I suggest to start from graphical inspection..
The plot of y(x) isn't encouraging. The plot of ln(y) as a function of x shows some regularly spaced steps.
This draw to introduce a periodic steps function into the equation model, for example the floor function.
We plot z(x)=ln(y)- a.floor(x/8)
With a=1.89 the curve becomes roughly continuous and smooth but not linear.
To make it roughly linear one have to plot it in log-log scales.
A linear regression leads to the parameters of the related power function roughly z=c.x**p. Thus we get :
NOTE : The criteria of fitting was LMSRE (with LMSE the numerical result would be different : Slightly better for high values of y and much worse for small y ).
I'm trying to cluster points in a 3D coordinates DataFrame of 1428 points.
The clusters are relatively flat planes that are elongated clouds DataFrame. They are very obvious clusters so I was hoping to try unsupervised clustering (not putting in the number of clusters expected) KMeans does not properly separate them and does require the number of clusters:
Kmeans plot results
The data looks as follows:
5 6 7
0 9207.495280 18922.083277 4932.864
1 5831.199280 3441.735280 5756.326
2 8985.735280 12511.719280 7099.844
3 8858.223280 28883.151280 5689.652
4 6801.399277 6468.759280 7142.524
... ... ... ...
1423 10332.927277 22041.855280 5136.252
1424 6874.971277 12937.563277 5467.216
1425 8952.471280 28849.887280 5710.522
1426 7900.611277 19128.255280 4803.122
1427 10234.635277 18734.631280 5631.286
[1428 rows x 3 columns]
I was hoping DBSCAN would deal better with this data. However, when I try the following (I played around with eps and min_samples but without success):
from sklearn.cluster import DBSCAN
dbscan = DBSCAN(eps=10, min_samples = 50)
clusters = dbscan.fit_predict(X)
print('Clusters found', dbscan.labels_)
len(clusters)
I get this output:
Clusters found [-1 -1 -1 ... -1 -1 -1]
1428
I have been confused about getting this to work, especially since Kmeans did work:
kmeans = sk_cluster.KMeans(init='k-means++', n_clusters=9, n_init=50)
kmeans.fit_predict(X)
centroids = kmeans.cluster_centers_
kmeans_labels = kmeans.labels_
error = kmeans.inertia_
print ("The total error of the clustering is: ", error)
print ('\nCluster labels')
The total error of the clustering is: 4994508618.792263
Cluster labels
[8 0 7 ... 3 8 1]
Remember this golden rule:
Always and always perform normalization on your data before feeding it to ML / DL algorithm.
Reason being, your columns have different range, probably one column has a range of [10000,20000] and other has [4000,5000] when you will plot these coordinates on a graph, they will be very very far away, Clustering/Classification will never work, maybe Regression will. Scaling brings the range of each of the column to same level but still maintaining the distance but with different scale. It is just like in google MAPS, when you zoom in scale decrease and when you zoom out scale increases.
You are free to choose the normalization algorithm, there are almost 20-30 available on sklearn.
Edit:
Use this code:
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaler.fit(X)
X_norm = scaler.transform(X)
from sklearn.cluster import DBSCAN
dbscan = DBSCAN(eps=0.05, min_samples = 3,leaf_size=30)
clusters = dbscan.fit_predict(X_norm)
np.unique(dbscan.labels_)
array([-1, 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])
What I found that as DBSCAN is a density based approach and I Tried sklearn normalizer(from sklearn.preprocessing import normalize) which basically converts into gaussian distribution, but it didn't work and it should not in case of DBSCAN as it requires each feature to have similar density.
So, I went with MinMax scaler as it should turn each features density similar and One thing to note, that as your data points after scaling, are less than 1, one should use epsilon in the similar range as well.
Kudos :)
I have a vector of time values in hh:mm format as well as a vector of values representing levels of activity.
For example:
x=[06:18, 07:58, 08:38, 09:18, 10:58];
y=[14, 28, 33, 68, 24];
Is it possible to plot a graph of y vs. x in Matlab?
If not, is there a way to display a vector of EPOCH time values as time in the format hh:mm, on the graph?
For example:
x= [1383260400, 1383261000, 1383261600, 1383262200, 1383262800];
y=[14, 28, 33, 68, 24];
Thanks in advance for your help
This should do the trick:
time={'06:18', '07:58', '08:38', '09:18', '10:58'};
data=[14, 28, 33, 68, 24];
ts = timeseries(data,time);
ts.TimeInfo.Format = 'HH:MM';
ts.TimeInfo.StartDate = '00:00';
plot(ts)
The time stamps must be in a cell array and apart from that it should be pretty self explanatory.
If you would like to plot more lines in the same plot and the same time stamps just use a matrix instead of a vector for the data:
data=[14, 28, 33, 68, 24; 7, 14, 35, 34, 12];
You could also change the TickLabels. This does not require Time Series object
time={'06:18', '07:58', '08:38', '09:18', '10:58'};
data=[14, 28, 33, 68, 24];
plot(data)
set(gca,'XTickLabel', time)
so this is my x and y data:
x = [29.745, 61.77, 42.57, 70.049, 108.51, 93.1, 135.47, 52.79, 77.91, 116.7, 100.71, 146.37, 125.53]
y = [6, 6, 12, 24, 24, 12, 24, 8, 24, 24, 24, 48, 8]
stem(x,y);
so i want to label each data point on my stem plot, this i want output i want:
i edit it using paint, can matlab do this vertical labeling? just what the image look like? please help.
Yes it can! You just need to provide the rotation property of text annotations with a value of 90 and it works fine.
Example:
clear
clc
x = [29.745, 61.77, 42.57, 70.049, 108.51, 93.1, 135.47, 52.79, 77.91, 116.7, 100.71, 146.37, 125.53]
y = [6, 6, 12, 24, 24, 12, 24, 8, 24, 24, 24, 48, 8]
hStem = stem(x,y);
%// Create labels.
Labels = {'none'; 'true';'false';'mean';'none';'';'true';'hints';'high';'low';'peas';'far';'mid'}
%// Get position of each stem 'bar'. Sorry I don't know how to name them.
X_data = get(hStem, 'XData');
Y_data = get(hStem, 'YData');
%// Assign labels.
for labelID = 1 : numel(X_data)
text(X_data(labelID), Y_data(labelID) + 3, Labels{labelID}, 'HorizontalAlignment', 'center','rotation',90);
end
Which gives the following:
The last label is a bit high so you might want to rescale the axes, but you get the idea.
The following are the inputs for my interpolation:
x = [-1.01, 5.66, 5.69, 13.77, 20.89]
y = [0.28773, 1.036889, 1.043178, 1.595322, 1.543763]
new_x = [0, 2, 4, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20]
The results from matlab interp1 and scipy.interpolate interp1d are different.
The results are like this.
new_y_scipy=[0.401171, 0.625806, 0.850442, 1.062384, 1.186291, 1.248244, 1.310198, 1.372152, 1.434105, 1.496059, 1.545429, 1.55267, 1.559911, 1.567153, 1.574394, 1.588877,]
new_y_matlab=[0.401171, 0.625806, 0.850442, 1.064362, 1.201031, 1.269366, 1.3377, 1.406035, 1.47437, 1.542704, 1.593656, 1.586415, 1.579174, 1.571932, 1.564691, 1.550208]
Apparently matlab seems to get better result than scipy. What is the fundamental difference?
I think that your data from scipy might be messed up somehow, because I can't reproduce your problem. For me, the results from scipy match perfectly with your results from matlab. See below for a demonstration:
import numpy as np
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt
x = [-1.01, 5.66, 5.69, 13.77, 20.89]
y = [0.28773, 1.036889, 1.043178, 1.595322, 1.543763]
new_x = [0, 2, 4, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20]
new_y_scipy=[0.401171, 0.625806, 0.850442, 1.062384, 1.186291, 1.248244, 1.310198, 1.372152, 1.434105, 1.496059, 1.545429, 1.55267, 1.559911, 1.567153, 1.574394, 1.588877,]
new_y_matlab=[0.401171, 0.625806, 0.850442, 1.064362, 1.201031, 1.269366, 1.3377, 1.406035, 1.47437, 1.542704, 1.593656, 1.586415, 1.579174, 1.571932, 1.564691, 1.550208]
askewchan = interp1d(x,y)(new_x)
# 'linear' has no effect since it's the default, but I'll plot it too:
set_interp = interp1d(x, y, kind='linear')
new_y = set_interp(new_x)
plt.plot(x, y, 'o', new_x, new_y_scipy, '--', new_x, new_y_matlab, ':', new_x, askewchan, '.', new_x, new_y, '+')
plt.legend(('Original','OP_scipy', 'OP_matlab', 'askewchan_scipy', 'OP style scipy'), loc='lower right')
np.allclose(new_y_matlab, interp1d(x,y)(new_x))
#True