programas - octave vs matlab
¿Cuál es tu truco de programación de MATLAB/Octave favorito? (30)
Creo que todos estarían de acuerdo en que el lenguaje de MATLAB no es bonito o particularmente consistente. ¡Pero no importa! Todavía tenemos que usarlo para hacer las cosas.
¿Cuáles son tus trucos favoritos para facilitar las cosas? Tengamos una por respuesta para que la gente pueda votar si están de acuerdo. Además, intente ilustrar su respuesta con un ejemplo.
x = repmat ([1:10], 3,1); % say, x es una matriz de datos de ejemplo
l = x> = 3; % l es un vector lógico (1s / 0s) para resaltar aquellos elementos en la matriz que cumplirían una determinada condición.
N = suma (suma (l));% N es la cantidad de elementos que cumplen esa condición dada.
¡Salud! ¡Escritura feliz!
¡Conozca las propiedades de su eje ! Hay todo tipo de cosas que puede configurar para ajustar las propiedades de trazado predeterminadas para hacer lo que desee:
set(gca,''fontsize'',8,''linestyleorder'',''-'',''linewidth'',0.3,''xtick'',1:2:9);
(como un ejemplo, establece el tamaño de fuente en 8pt, los estilos de línea de todas las líneas nuevas para que sean sólidos y su ancho 0,3 pt, y los puntos xtick sean [1 3 5 7 9])
Line propiedades de Line y figure también son útiles, pero me resulta más útil usar propiedades de ejes.
-Puede hacer un acceso directo de Matlab a un archivo de inicialización llamado startup.m. Aquí, defino el formato, la precisión de la salida y los parámetros de trazado para mi sesión de Matlab (por ejemplo, utilizo un eje / tamaño de letra más grande para que se vea claramente .fig cuando los pongo en presentaciones.) Vea un buen publicación de blog de uno de los desarrolladores al respecto http://blogs.mathworks.com/loren/2009/03/03/whats-in-your-startupm/ .
-Puede cargar un archivo ascii numérico completo usando la función "cargar". Esto no es particularmente rápido, pero hace el trabajo rápidamente para crear prototipos (¿no debería ser ese el lema de Matlab?)
-Como se mencionó, el operador de colon y la vectorización son salvavidas. Atornille los bucles.
Aquí hay un ejemplo rápido:
Encuentro la sintaxis de la lista separada por comas bastante útil para construir llamadas a funciones:
% Build a list of args, like so:
args = {''a'', 1, ''b'', 2};
% Then expand this into arguments:
output = func(args{:})
Aquí hay un montón de funciones no evidentes que son útiles de vez en cuando:
-
mfilename
(devuelve el nombre del script MATLAB actualmente en ejecución) -
dbstack
(le da acceso a los nombres y números de línea de la pila de funciones de matlab) -
keyboard
(detiene la ejecución y cede el control a la solicitud de depuración, esta es la razón por la cual hay una K en el indicador de depuraciónK>>
-
dbstop error
(lo pone automáticamente en modo de depuración detenido en la línea que desencadena un error)
Convierta una matriz en un vector usando un solo colon.
x = rand(4,4);
x(:)
Ejecutar un modelo Simulink directamente desde un script (en lugar de interactivamente) usando el comando sim
. Puede hacer cosas como tomar parámetros de una variable de espacio de trabajo, y ejecutar sim
repetidamente en un bucle para simular algo mientras se varía el parámetro para ver cómo cambia el comportamiento, y graficar los resultados con los comandos gráficos que desee. Mucho más fácil que tratar de hacer esto de forma interactiva, y le da mucha más flexibilidad que los bloques de "osciloscopio" de Simulink al visualizar los resultados. (aunque no puede usarlo para ver lo que está sucediendo en tiempo real mientras se ejecuta la simulación)
Una cosa realmente importante que debe saber es las opciones DstWorkspace
y SrcWorkspace
del comando simset
. Estos controlan dónde los bloques "Para el espacio de trabajo" y "Del área de trabajo" obtienen y colocan sus resultados. Dstworkspace
predeterminado en el espacio de trabajo actual (por ejemplo, si llama a sim
desde dentro de una función, los bloques "Al espacio de trabajo" aparecerán como variables accesibles desde esa misma función) pero SrcWorkspace
predeterminada en el espacio de trabajo base y si desea encapsular su llamada a sim
, querrá configurar SrcWorkspace
a la current
modo que haya una interfaz limpia para proporcionar / recuperar los parámetros y salidas de entrada de simulación. Por ejemplo:
function Y=run_my_sim(t,input1,params)
% runs "my_sim.mdl"
% with a From Workspace block referencing I1 as an input signal
% and parameters referenced as fields of the "params" structure
% and output retrieved from a To Workspace block with name O1.
opt = simset(''SrcWorkspace'',''current'',''DstWorkspace'',''current'');
I1 = struct(''time'',t,''signals'',struct(''values'',input1,''dimensions'',1));
Y = struct;
Y.t = sim(''my_sim'',t,opt);
Y.output1 = O1.signals.values;
El operador de dos puntos para la manipulación de matrices.
@ ScottieT812, menciona uno: aplanar una matriz, pero hay todas las otras variantes de selección de bits de una matriz:
x=rand(10,10);
flattened=x(:);
Acolumn=x(:,10);
Arow=x(10,:);
y=rand(100);
firstSix=y(1:6);
lastSix=y(end-5:end);
alternate=y(1:2:end);
Extracción directa de los elementos de una matriz que satisfacen una condición particular, utilizando matrices lógicas:
x = rand(1,50) .* 100;
xpart = x( x > 20 & x < 35);
Ahora xpart contiene solo aquellos elementos de x que se encuentran en el rango especificado.
Funciones anónimas, por algunas razones:
- para hacer una función rápida para usos únicos, como 3x ^ 2 + 2x + 7. (Consulte la lista a continuación) Esto es útil para funciones como
quad
yfminbnd
que toman funciones como argumentos. También es conveniente en scripts (archivos .m que no comienzan con un encabezado de función) ya que a diferencia de las funciones verdaderas no puede incluir subfunciones. - para closures , aunque las funciones anónimas son un poco limitantes ya que no parece haber una manera de tener asignaciones dentro de ellas para mutar el estado.
.
% quick functions
f = @(x) 3*x.^2 + 2*x + 7;
t = (0:0.001:1);
plot(t,f(t),t,f(2*t),t,f(3*t));
% closures (linfunc below is a function that returns a function,
% and the outer functions arguments are held for the lifetime
% of the returned function.
linfunc = @(m,b) @(x) m*x+b;
C2F = linfunc(9/5, 32);
F2C = linfunc(5/9, -32*5/9);
Gráficos de contorno con [c,h]=contour
y clabel(c,h,''fontsize'',fontsize)
. Usualmente uso el parámetro fontsize
para reducir el tamaño de fuente para que los números no se encuentren entre sí. Esto es ideal para ver el valor de las funciones 2-D sin tener que ensuciar con gráficos 3D.
Invocar código Java de Matlab
Las bsxfun , arrayfun , cellfun y structfun son bastante interesantes y, a menudo, guardan un bucle.
M = rand(1000, 1000);
v = rand(1000, 1);
c = bsxfun(@plus, M, v);
Este código, por ejemplo, agrega column-vector v a cada columna de la matriz M.
Sin embargo, en las partes críticas del rendimiento de su aplicación, debe comparar estas funciones con el for-loop trivial porque a menudo los bucles son aún más rápidos.
Me gusta usar los identificadores de función por muchas razones. Por un lado, son lo más parecido que he encontrado en MATLAB a los punteros, por lo que puede crear un comportamiento de referencia para los objetos. También hay algunas cosas ordenadas (y más simples) que puedes hacer con ellas. Por ejemplo, reemplazando una declaración de interruptor:
switch number,
case 1,
outargs = fcn1(inargs);
case 2,
outargs = fcn2(inargs);
...
end
%
%can be turned into
%
fcnArray = {@fcn1, @fcn2, ...};
outargs = fcnArray{number}(inargs);
Solo creo que pequeñas cosas así son geniales.
Me sorprende que mientras las personas mencionaban el enfoque de matriz lógica para indexar una matriz, nadie mencionó el comando de búsqueda.
por ejemplo, si x es una matriz NxMxO
x (x> 20) funciona generando una matriz lógica NxMxO y usándola para indexar x (lo cual puede ser malo si tiene matrices grandes y está buscando un subconjunto pequeño
x (find (x> 20)) funciona generando una lista (es decir, 1xwhatever) de índices de x que satisfacen x> 20, e indexando x por ella. "Encontrar" debería usarse más de lo que es, en mi experiencia.
Más de lo que yo llamaría ''trucos''
puede crecer / anexarse a matrices y matrices de celdas si no conoce el tamaño que necesitará, utilizando end + 1 (también trabaja con dimensiones superiores, siempre que las dimensiones de la división coincidan, por lo que tiene que inicializar x a algo que no sea [] en ese caso). No es bueno para los numéricos, sino para pequeñas listas dinámicas de cosas (o matrices de celdas), por ejemplo, análisis de archivos.
p.ej
>> x=[1,2,3] x = 1 2 3 >> x(end+1)=4 x = 1 2 3 4
Otra cosa que mucha gente no sabe es que funciona en cualquier matriz dim 1, así que para continuar el ejemplo
>> for n = x;disp(n);end 1 2 3 4
Lo que significa que si todo lo que necesita son los miembros de x, no necesita indexarlos.
Esto también funciona con matrices de celdas, pero es un poco molesto porque a medida que las recorre, el elemento sigue envuelto en una celda:
>> for el = {1,2,3,4};disp(el);end [1] [2] [3] [4]
Entonces, para llegar a los elementos tienes que subíndices
>> for el = {1,2,3,4};disp(el{1});end 1 2 3 4
No recuerdo si hay una manera más agradable de evitar eso.
Oh, e invertir una matriz
v = 1:10;
v_reverse = v(length(v):-1:1);
Para poder probar rápidamente una función, utilizo nargin
manera:
function result = multiply(a, b)
if nargin == 0 %no inputs provided, run using defaults for a and b
clc;
disp(''RUNNING IN TEST MODE'')
a = 1;
b = 2;
end
result = a*b;
Más tarde, agrego un script de prueba de unidad para probar la función para diferentes condiciones de entrada.
Preguntar "por qué" (útil para sacudirme de un trance de depuración de Matlab en tiempo de ejecución a las 3 de la mañana ...)
Proporcione acceso rápido a la documentación de otras funciones agregando una línea "VER TAMBIÉN" a los comentarios de ayuda. Primero, debe incluir el nombre de la función en mayúsculas como primera línea de comentario. Haga su comentario habitual en el encabezado, luego, VEA TAMBIÉN una lista separada por comas de otras funciones relacionadas.
function y = transmog(x)
%TRANSMOG Transmogrifies a matrix X using reverse orthogonal eigenvectors
%
% Usage:
% y = transmog(x)
%
% SEE ALSO
% UNTRANSMOG, TRANSMOG2
Cuando escribe "help transmog" en la línea de comandos, verá todos los comentarios en este encabezado de comentario, con hipervínculos a los encabezados de comentario para las otras funciones enumeradas.
Sea estricto al especificar las dimensiones al usar funciones de agregación como min, max, mean, diff, sum, any, all, ...
Por ejemplo, la línea:
reldiff = diff(a) ./ a(1:end-1)
podría funcionar bien para calcular las diferencias relativas de los elementos en un vector, sin embargo, en caso de que el vector degenere en un solo elemento, el cálculo falla:
>> a=rand(1,7);
>> diff(a) ./ a(1:end-1)
ans =
-0.5822 -0.9935 224.2015 0.2708 -0.3328 0.0458
>> a=1;
>> diff(a) ./ a(1:end-1)
??? Error using ==> rdivide
Matrix dimensions must agree.
Si especifica las dimensiones correctas para sus funciones, esta línea devuelve una matriz vacía de 1 por 0, que es correcta:
>> diff(a, [], 2) ./ a(1, 1:end-1)
ans =
Empty matrix: 1-by-0
>>
Lo mismo ocurre con una función mínima que generalmente calcula mínimos sobre columnas en una matriz, hasta que la matriz solo conste de una fila. - Entonces devolverá el mínimo sobre la fila a menos que el parámetro de dimensión indique lo contrario, y probablemente rompa su aplicación.
Casi puedo garantizarle que, en consecuencia, establecer las dimensiones de estas funciones de agregación le ahorrará bastante trabajo de depuración más adelante.
Al menos ese hubiera sido el caso para mí. :)
Usando el generador de perfiles integrado para ver dónde están las partes más importantes de mi código:
profile on
% some lines of code
profile off
profile viewer
o simplemente usando el tic
y toc
integrados para obtener sincronizaciones rápidas:
tic;
% some lines of code
toc;
Usando xlim y ylim para dibujar líneas verticales y horizontales. Ejemplos:
Dibuja una línea horizontal en y = 10:
line(xlim, [10 10])
Dibuja una línea vertical en x = 5:
line([5 5], ylim)
Usar ismember () para combinar datos organizados por los identificadores de texto. Es útil cuando se analizan diferentes períodos cuando las entradas, en mi caso, símbolos de la compañía, aparecen y desaparecen.
%Merge B into A based on Text identifiers
UniverseA = {''A'',''B'',''C'',''D''};
UniverseB = {''A'',''C'',''D''};
DataA = [20 40 60 80];
DataB = [30 50 70];
MergeData = NaN(length(UniverseA),2);
MergeData(:,1) = DataA;
[tf, loc] = ismember(UniverseA, UniverseB);
MergeData(tf,2) = DataB(loc(tf));
MergeData =
20 30
40 NaN
60 50
80 70
Usar nargin para establecer valores predeterminados para argumentos opcionales y usar nargout para establecer argumentos de salida opcionales. Ejemplo rápido
function hLine=myplot(x,y,plotColor,markerType)
% set defaults for optional paramters
if nargin<4, markerType=''none''; end
if nargin<3, plotColor=''k''; end
hL = plot(x,y,''linetype'',''-'', ...
''color'',plotColor, ...
''marker'',markerType, ...
''markerFaceColor'',plotColor,''markerEdgeColor'',plotColor);
% return handle of plot object if required
if nargout>0, hLine = hL; end
Usar variables persistent
(estáticas) cuando se ejecuta un algoritmo en línea. Puede acelerar el código en áreas como el aprendizaje bayesiano automático, donde el modelo se entrena de forma iterativa para las nuevas muestras. Por ejemplo, para calcular las loglikelihoods independientes, calculo la loglikelihood inicialmente desde cero y la actualizo sumando esta loglikelihood previamente calculada y la loglikelihood adicional.
En lugar de dar un problema de aprendizaje automático más especializado, permítanme darles un código de promedio general en línea que tomé de aquí :
function av = runningAverage(x)
% The number of values entered so far - declared persistent.
persistent n;
% The sum of values entered so far - declared persistent.
persistent sumOfX;
if x == ''reset'' % Initialise the persistent variables.
n = 0;
sumOfX = 0;
av = 0;
else % A data value has been added.
n = n + 1;
sumOfX = sumOfX + x;
av = sumOfX / n; % Update the running average.
end
Entonces, las llamadas darán los siguientes resultados
runningAverage(''reset'')
ans = 0
>> runningAverage(5)
ans = 5
>> runningAverage(10)
ans = 7.5000
>> runningAverage(3)
ans = 6
>> runningAverage(''reset'')
ans = 0
>> runningAverage(8)
ans = 8
Vectorización:
function iNeedle = findClosest(hay,needle)
%FINDCLOSEST find the indicies of the closest elements in an array.
% Given two vectors [A,B], findClosest will find the indicies of the values
% in vector A closest to the values in vector B.
[hay iOrgHay] = sort(hay(:)''); %#ok must have row vector
% Use histogram to find indices of elements in hay closest to elements in
% needle. The bins are centered on values in hay, with the edges on the
% midpoint between elements.
[iNeedle iNeedle] = histc(needle,[-inf hay+[diff(hay)/2 inf]]); %#ok
% Reversing the sorting.
iNeedle = iOrgHay(iNeedle);
argumentos condicionales en el lado izquierdo de una tarea:
t = (0:0.005:10)'';
x = sin(2*pi*t);
x(x>0.5 & t<5) = 0.5;
% This limits all values of x to a maximum of 0.5, where t<5
plot(t,x);
cellfun y arrayfun para bucles automatizados.
Modo LaTeX para fórmulas en gráficos : en una de las versiones recientes (R2006?) Usted agrega los argumentos adicionales ,''Interpreter'',''latex''
al final de una llamada a función y utilizará la representación LaTeX. Aquí hay un ejemplo:
t=(0:0.001:1);
plot(t,sin(2*pi*[t ; t+0.25]));
xlabel(''t'');
ylabel(''$/hat{y}_k=sin 2/pi (t+{k /over 4})$'',''Interpreter'',''latex'');
legend({''$/hat{y}_0$'',''$/hat{y}_1$''},''Interpreter'',''latex'');
No estoy seguro de cuándo lo agregaron, pero funciona con R2006b en las funciones text (), title (), xlabel (), ylabel (), zlabel () e incluso legend (). Solo asegúrese de que la sintaxis que está utilizando no sea ambigua (por lo que con legend () debe especificar las cadenas como una matriz de celdas).
Vectorizar bucles . Hay muchas maneras de hacerlo, y es entretenido buscar loops en su código y ver cómo se pueden vectorizar. ¡El rendimiento es asombrosamente más rápido con operaciones vectoriales!