On Windows 10, I have installed Anaconda and launched Spyder. I have also successfully installed Theano, Tensorflow and Keras, since when I execute
import keras
the console outputs
Using Tensorflow Backend
When I compile and fit the neural network it runs fine. But when I try to run k-fold cross validation, combining the scikit-learn via a keras wrapper and using the parameter n_jobs = -1 (and generally n_jobs with whatever value, thus having multiprocessing), the console just freezes forever until restarting kernel manually or terminating Spyder.
Another problem, when I try to run some parameter tuning using GridSearchCV, for i.e. 100 epochs, it doesn't freeze but it outputs epoch 1/1 instead of 1/100 and generally it gives bad results, not logical (i.e. it runs only for a couple of minutes, while normally it would take hours!).
My code is:
# Part 1 - Data Preprocessing
# Importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# Importing the dataset
dataset = pd.read_csv('Churn_Modelling.csv')
X = dataset.iloc[:, 3:13].values
y = dataset.iloc[:, 13].values
# Encoding categorical data
# Encoding the Independent Variable
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
labelencoder_X_1 = LabelEncoder()
X[:, 1] = labelencoder_X_1.fit_transform(X[:, 1])
labelencoder_X_2 = LabelEncoder()
X[:, 2] = labelencoder_X_2.fit_transform(X[:, 2])
onehotencoder = OneHotEncoder(categorical_features = [1])
X = onehotencoder.fit_transform(X).toarray()
# Avoiding the dummy variable trap
X = X[:, 1:]
# Splitting the dataset into the Training set and Test set
from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)
# Feature Scaling
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
# Part 2 - Now let's make the ANN!
# Importing the Keras libraries and packages
import keras
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
# Initialising the ANN
classifier = Sequential()
# Adding the input layer and the first hidden layer with dropout
classifier.add(Dense(units = 6, kernel_initializer = 'uniform', activation = 'relu', input_dim = 11))
classifier.add(Dropout(rate = 0.1)) # p should vary from 0.1 to 0.4, NOT HIGHER, because then we will have under-fitting.
# Adding the second hidden layer with dropout
classifier.add(Dense(units = 6, kernel_initializer = 'uniform', activation = 'relu'))
classifier.add(Dropout(rate = 0.1))
# Adding the output layer
classifier.add(Dense(units = 1, kernel_initializer = 'uniform', activation = 'sigmoid'))
# Compiling the ANN
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
# Fitting the ANN to the Training set
classifier.fit(X_train, y_train, batch_size = 10, epochs = 100)
# Part 3 - Making predictions and evaluating the model
# Predicting the Test set results
y_pred = classifier.predict(X_test)
y_pred = (y_pred > 0.5)
# Making the Confusion Matrix
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, y_pred)
new_prediction = classifier.predict(sc.transform(np.array([[0, 0, 600, 1, 40, 3, 60000, 2, 1, 1, 50000]])))
new_prediction = (new_prediction > 0.5)
#Part 4 = Evaluating, Improving and Tuning the ANN
# Evaluating the ANN
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import cross_val_score
from keras.models import Sequential
from keras.layers import Dense
def build_classifier():
classifier = Sequential()
classifier.add(Dense(units = 6, kernel_initializer = 'uniform', activation = 'relu', input_dim = 11))
classifier.add(Dense(units = 6, kernel_initializer = 'uniform', activation = 'relu'))
classifier.add(Dense(units = 1, kernel_initializer = 'uniform', activation = 'sigmoid'))
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
return classifier
classifier = KerasClassifier(build_fn = build_classifier, batch_size = 10, nb_epoch = 100)
accuracies = cross_val_score(estimator = classifier, X = X_train, y = y_train, cv = 10, n_jobs = -1)
mean = accuracies.mean()
variance = accuracies.std()
# Improving the ANN
# Tuning the ANN
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import GridSearchCV
from keras.models import Sequential
from keras.layers import Dense
def build_classifier(optimizer):
classifier = Sequential()
classifier.add(Dense(units = 6, kernel_initializer = 'uniform', activation = 'relu', input_dim = 11))
classifier.add(Dense(units = 6, kernel_initializer = 'uniform', activation = 'relu'))
classifier.add(Dense(units = 1, kernel_initializer = 'uniform', activation = 'sigmoid'))
classifier.compile(optimizer = optimizer, loss = 'binary_crossentropy', metrics = ['accuracy'])
return classifier
classifier = KerasClassifier(build_fn = build_classifier)
parameters = {"batch_size": [25, 32],
"nb_epoch": [100, 500],
"optimizer": ["adam", "rmsprop"]}
grid_search = GridSearchCV(estimator = classifier,
param_grid = parameters,
scoring = "accuracy",
cv = 10)
grid_search = grid_search.fit(X_train, y_train)
best_parameters = grid_search.best_params_
best_accuracy = grid_search.best_score_
Also, for n_jobs = 1, it runs but says epoch 1/1 and runs 10 times, which is the k-fold value. That means that it recognizes nb_epoch = 1 and not 100 for some reason.
Finally, I tried enclosing the cross_val_score() into a class:
class run():
def __init__(self):
cross_val_score(estimator = classifier, X = X_train, y = y_train, cv = 10, n_jobs = -1)
if __name__ == '__main__':
run()
or have it only with the if condition:
if __name__ == '__main__':
cross_val_score(estimator = classifier, X = X_train, y = y_train, cv = 10, n_jobs = -1)
but it doesn't work either, it freezes again.
Can anyone help me out solving these issues? What is going on, what can I do to solve these so everything runs properly?
Thank you in advance.
it seems Windows has an issue with "n_jobs", remove it in your "accuracies=" code and it will work, downside is it may take a while but at least it will work.
Related
I am trying use PYMC3 to implement an example where the data comes from a mixture of multinomials. The goal is to infer the underlying state_prob vector (see below). The code runs, but the Metropolis sampler gets stuck at the initial state_prior vector. Also, for some reason I have not been able to get NUTS to work.
import numpy as np
import pandas as pd
from pymc3 import Model, Multinomial, Dirichlet
import pymc3
import theano.tensor as tt
from theano import function, printing
N = 10
state_prior = np.array([.3, .3, .3])
state_prob = np.array([0.3, 0.1, 0.6]) #need to infer this
state_emission_tran = np.array([[0.3, 0.2, 0.5],
[0.1, 0.5, 0.4],
[0.0, 0.05, 0.95]])
state_data = np.random.multinomial(1, state_prob, size=N)
emission_prob_given_state = np.matmul(state_data, state_emission_tran)
def rand_mult(row_p):
return np.random.multinomial(1, row_p)
emission_data = np.apply_along_axis(rand_mult, 1, emission_prob_given_state)
# done with creating data
with Model() as simple_dag:
state = Dirichlet('state', state_prior*100, shape=3)
emission_dist = [pymc3.Multinomial.dist(p=state_emission_tran[i], n=1, shape=3) for i in range(3)]
emission_mix = pymc3.Mixture('emission_mix', w = state, comp_dists = emission_dist, observed=emission_data)
with simple_dag:
step = pymc3.Metropolis(vars=[state])
trace = pymc3.sample(10000, cores=2, chains=2, tune=500, step=step, progressbar=True)
Try this one:
import numpy as np
import pandas as pd
from pymc3 import Model, Multinomial, Dirichlet
import pymc3
import theano.tensor as tt
from theano import function, printing
N = 10
state_prior = np.array([.3, .3, .3])
state_prob = np.array([0.3, 0.1, 0.6]) #need to infer this
state_emission_tran = np.array([[0.3, 0.2, 0.5],
[0.1, 0.5, 0.4],
[0.0, 0.05, 0.95]])
state_data = np.random.multinomial(1, state_prob, size=N)
emission_prob_given_state = np.matmul(state_data, state_emission_tran)
def rand_mult(row_p):
return np.random.multinomial(1, row_p)
emission_data = np.apply_along_axis(rand_mult, 1, emission_prob_given_state)
# done with creating data
with Model() as simple_dag:
state = Dirichlet('state', state_prior*100, shape=3)
emission_dist = [pymc3.Multinomial.dist(p=state_emission_tran[i], n=1, shape=3) for i in range(3)]
emission_mix = pymc3.Mixture('emission_mix', w = state, comp_dists = emission_dist, observed=emission_data)
with simple_dag:
trace = pymc3.sample(3000, tune=1000)
I am using pymc3 version 3.5 in Linux and it works fine.
I try to train a CNN model, 2 classes, which is based on tensorflow to do the image classification.
I have tried much modification about epochs, learning rate, batch size and the CNN size, but nothing works.
about data
86(label: 0) + 63(label: 1) images
shape: (128, 128)
about current parameters
learning_rate = 0.00005(I have tried from 0.00000001 to 0.8...)
batch size = 30(I also have tried from 5 to 130)
epoch = 20
about network
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev = 0.1, dtype = tf.float32)
return tf.Variable(initial)
def bias_variable(shape):
initial = tf.constant(0.1, shape = shape, dtype = tf.float32)
return tf.Variable(initial)
def conv2d(x, W):
#(input, filter, strides, padding)
#[batch, height, width, in_channels]
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
def max_pool_2x2(x):
#(value, ksize, strides, padding)
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
def cnn_model():
epochs = 20
batch_size = 30
learning_rate = 0.00005
hidden = 2
cap_c = 86
cap_h = 63
num = cap_c + cap_h
image_size = 128
label_size = 2
print ((num//(batch_size)) * epochs)
train_loss = np.empty((num//(batch_size)) * epochs)
train_acc = np.empty((num//(batch_size)) * epochs)
x = tf.placeholder(tf.float32, shape = [None, image_size, image_size])
y = tf.placeholder(tf.float32, shape = [None, label_size])
weight_balance = tf.constant([0.1])
X_train_ = tf.reshape(x, [-1, image_size, image_size, 1])
#First layer
W_conv1 = weight_variable([5, 5, 1, 4])
b_conv1 = bias_variable([4])
h_conv1 = tf.nn.relu(conv2d(X_train_, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
# #Second layer
# W_conv2 = weight_variable([5, 5, 4, 8])
# b_conv2 = bias_variable([8])
#
# h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
# h_pool2 = max_pool_2x2(h_conv2)
#
# Third layer
# W_conv3 = weight_variable([5, 5, 8, 16])
# b_conv3 = bias_variable([16])
#
# h_conv3 = tf.nn.relu(conv2d(h_pool2, W_conv3) + b_conv3)
# h_pool3 = max_pool_2x2(h_conv3)
#Full connect layer
W_fc1 = weight_variable([64 * 64 * 4, hidden])
b_fc1 = bias_variable([hidden])
h_pool2_flat = tf.reshape(h_pool1, [-1, 64 * 64 * 4])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
#Output_Softmax
W_fc2 = weight_variable([hidden, label_size])
b_fc2 = bias_variable([label_size])
y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
print y_conv.shape
#Train
loss = tf.reduce_mean(tf.nn.weighted_cross_entropy_with_logits(y, y_conv, weight_balance))
optimize = tf.train.AdamOptimizer(learning_rate).minimize(loss)
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
about result
The loss is not convergent and also the accuracy.
I don't know if my CNN model is not suitable for my data?
or
The Activate function and loss function of the network is not suitable?
Really thank you
There are couple of problems with the code:
You are applying softmax on the last layer and then calling tf.nn.weighted_cross_entropy_with_logits which in turn applies sigmoid activation, so you are applying activation twice.
For initialisation of the weights, use Xavier or Variance_scaling for faster convergence. Better to use tf.layers API in implementing your model as its default settings follows best practices.
I am trying to animate a live graph in a wx.Panel. I would like to have the x-axis update like this example. Many of the examples I see are basic and don't take into consideration other controls and functions in the class. Others have so many extras that I get lost in the weeds. I can't get the animation command in the right place or update the x-axis. Here is the code:
import wx
import logging
import numpy as np
import matplotlib
import time
import matplotlib.animation as animation
matplotlib.use('WXAgg')
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx
from matplotlib.figure import Figure
fTemp = ""
x = 0
class TempClass(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, title="", size=(600,500))
panel = wx.Panel(self)
self.fig = Figure(figsize=(6,4), dpi=75, facecolor='lightskyblue', edgecolor='r')
self.canvas = FigureCanvas(self, -1, self.fig)
self.ax = self.fig.add_subplot(111)
self.ax2 = self.ax.twinx()
self.ax.set_ylim(60,90)
self.ax.set_xlim(0,24)
self.ax2.set_ylim(0,100)
# major ticks every 5, minor ticks every 1
xmajor_ticks = np.arange(0, 24, 5)
xminor_ticks = np.arange(0, 24, 1)
self.ax.set_xticks(xmajor_ticks)
self.ax.set_xticks(xminor_ticks, minor=True)
self.ax.grid()
self.ax.set_xlabel('Hour')
self.ax.set_ylabel('Temp')
self.ax2.set_ylabel('Humidity')
self.ax.set_title('Temperature')
# The graph does not show in the panel when this in uncommented
#self.ani = animation.FuncAnimation(self.fig, self.onPlotTemp, interval=1000)
self.fanSensorTimer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.onPlotTemp, self.fanSensorTimer)
self.fanSensorBtn = wx.Button(self, -1, "Start Sensor")
self.Bind(wx.EVT_BUTTON, self.onStartTempPlot, self.fanSensorBtn)
font1 = wx.Font(18, wx.DEFAULT,wx.NORMAL,wx.BOLD)
self.displayTemp = wx.StaticText(self, -1, "Current Tempurature")
self.curTempTxt = wx.TextCtrl(self, -1, "0",size=(100,40), style=wx.TE_READONLY|wx.TE_CENTRE|wx.BORDER_NONE)
self.curTempTxt.SetFont(font1)
self.displayHum = wx.StaticText(self, -1, "Current Humidity")
self.curHumTxt = wx.TextCtrl(self, -1,"0", size=(100,40), style=wx.TE_READONLY|wx.TE_CENTRE|wx.BORDER_NONE)
self.curHumTxt.SetFont(font1)
self.displayBox = wx.GridBagSizer(hgap=5,vgap=5)
self.displayBox.Add(self.displayTemp, pos=(0,0), flag=wx.TOP|wx.LEFT, border=5)
self.displayBox.Add(self.displayHum, pos=(0,1), flag=wx.TOP, border=5)
self.displayBox.Add(self.curTempTxt, pos=(1,0), flag=wx.ALL, border=5)
self.displayBox.Add(self.curHumTxt, pos=(1,1), flag=wx.ALL, border=5)
#---------
self.vbox = wx.BoxSizer(wx.VERTICAL)
self.vbox.Add(self.canvas, wx.ALIGN_CENTER|wx.ALL, 1)
self.vbox.Add(self.fanSensorBtn)
self.vbox.Add(self.displayBox, wx.ALIGN_CENTER|wx.ALL, 1)
self.SetSizer(self.vbox)
self.vbox.Fit(self)
def start(self):
# get temp/humidity reading from node
pass
def readTemp(self, data1, data2):
"Populates Current Temp"
global fTemp
self.curTempTxt.Clear()
a = format(data1, '08b')
b = format(data2, '08b')
x = a+b
y = int(x, base=2)
cTemp = ((175.72 * y)/65536)-46.85
fTemp = cTemp *1.8+32
cel = format(cTemp,'.1f')
far = format(fTemp,'.1f')
self.curTempTxt.WriteText(far + (u'\u00b0')+"F")
def rh1(self, data1, data2):
"Populates Current RH"
global relhum
self.curHumTxt.Clear()
a = format(data1, '08b')
b = format(data2, '08b')
x = a+b
y = int(x, base=2)
rh = ((125 * y)/65536)-6
relhum = format(rh,'.1f')
self.curHumTxt.WriteText(relhum + " %")
def onStartTempPlot(self,event):
#set for a short time period for testing purposes
self.fanSensorTimer.Start(5000)
print "Timer Started"
def onPlotTemp(self,event):
global fTemp, x, relhum
x +=1
y = int(fTemp)
y2 = float(relhum)
self.ax.plot(x,y,'r.')
self.ax2.plot(x,y2,'k.')
self.fig.canvas.draw()
# send message to node for another reading of temp/humidity
if __name__ == "__main__":
app = wx.App(False)
frame = TempClass()
frame.Show()
frame.start()
logging.basicConfig(level=logging.DEBUG)
app.MainLoop()
I would like to see the x axis increment as the data is plotted beyond the 24 hour point on the graph; when data for point 25 appears, the first point is dropped and the x axis shows '25'. The animation is commented out because it causes the graph to disappear until a point is plotted.
Here is a runnable example of what I am trying to achieve with the x axis:
import numpy
from matplotlib.pylab import *
from mpl_toolkits.axes_grid1 import host_subplot
import matplotlib.animation as animation
# Sent for figure
font = {'size' : 9}
matplotlib.rc('font', **font)
# Setup figure and subplots
f0 = figure(num = 0, figsize = (6, 4))#, dpi = 100)
f0.suptitle("Oscillation decay", fontsize=12)
ax01 = subplot2grid((2, 2), (0, 0))
# Set titles of subplots
ax01.set_title('Position vs Time')
# set y-limits
ax01.set_ylim(0,2)
# sex x-limits
ax01.set_xlim(0,1)
# Turn on grids
ax01.grid(True)
# set label names
ax01.set_xlabel("x")
ax01.set_ylabel("py")
# Data Placeholders
yp1=zeros(0)
yv1=zeros(0)
yp2=zeros(0)
yv2=zeros(0)
t=zeros(0)
# set plots
p011, = ax01.plot(t,yp1,'b-', label="yp1")
p012, = ax01.plot(t,yp2,'g-', label="yp2")
# set lagends
ax01.legend([p011,p012], [p011.get_label(),p012.get_label()])
# Data Update
xmin = 0
xmax = 24
x = 0
def updateData(self):
global x
global yp1
global yv1
global yp2
global yv2
global t
tmpp1 = 1 + exp(-x) *sin(2 * pi * x)
tmpv1 = - exp(-x) * sin(2 * pi * x) + exp(-x) * cos(2 * pi * x) * 2 * pi
yp1=append(yp1,tmpp1)
yv1=append(yv1,tmpv1)
yp2=append(yp2,0.5*tmpp1)
yv2=append(yv2,0.5*tmpv1)
t=append(t,x)
x += 1
p011.set_data(t,yp1)
p012.set_data(t,yp2)
if x >= xmax-1:
p011.axes.set_xlim(x-xmax+1,x+1)
return p011
# interval: draw new frame every 'interval' ms
# frames: number of frames to draw
simulation = animation.FuncAnimation(f0, updateData, blit=False, frames=200, interval=20, repeat=False)
plt.show()
You are not incrementing the X axis limit or the ticks.
def onPlotTemp(self,event):
global fTemp, x, relhum
x +=1
y = int(fTemp)
y2 = float(relhum)
if x >= 24-1:
self.ax.set_xlim(x-24+1,x+1)
xmajor_ticks = np.arange(x-24+1,x+5, 5)
xminor_ticks = np.arange(x-24+1, x+1,1)
self.ax.set_xticks(xmajor_ticks)
self.ax.set_xticks(xminor_ticks, minor=True)
self.ax.plot(x,y,'r.')
self.ax2.plot(x,y2,'k.')
self.fig.canvas.draw()
I'm not sure if the above resets the ticks the way you want them but you get the idea. Obviously I have hard-coded 24 as your limit, you may want to create a variable to sort that out.
how to build 152-layer resnet and extract the penultimate hidden layer's image feature.
now I got a pre-trained ResNet 152-layer model http://download.tensorflow.org/models/resnet_v1_152_2016_08_28.tar.gz
I just want to use this 152-layer model to extract the image feature, now i want to extract the penultimate hidden layer's image feature
(just as show in the code).
The main question is how to build 152-layer ResNet model ? (i just see that set n = 18 then resnet
is 110 layers.). Or how to build 50-layer ResNet model?
my extract the penultimate hidden layer's image feature code is right?
from __future__ import division, print_function, absolute_import
import tflearn
from PIL import Image
import numpy as np
# Residual blocks
# 32 layers: n=5, 56 layers: n=9, 110 layers: n=18
n = 18
# Data loading
from tflearn.datasets import cifar10
(X, Y), (testX, testY) = cifar10.load_data()
Y = tflearn.data_utils.to_categorical(Y, 10)
testY = tflearn.data_utils.to_categorical(testY, 10)
# Real-time data preprocessing
img_prep = tflearn.ImagePreprocessing()
img_prep.add_featurewise_zero_center(per_channel=True)
# Real-time data augmentation
img_aug = tflearn.ImageAugmentation()
img_aug.add_random_flip_leftright()
img_aug.add_random_crop([32, 32], padding=4)
# Building Residual Network
net = tflearn.input_data(shape=[None, 32, 32, 3],
data_preprocessing=img_prep,
data_augmentation=img_aug)
net = tflearn.conv_2d(net, 16, 3, regularizer='L2', weight_decay=0.0001)
net = tflearn.residual_block(net, n, 16)
net = tflearn.residual_block(net, 1, 32, downsample=True)
net = tflearn.residual_block(net, n-1, 32)
net = tflearn.residual_block(net, 1, 64, downsample=True)
net = tflearn.residual_block(net, n-1, 64)
net = tflearn.residual_block(net, 1, 64, downsample=True)
net = tflearn.residual_block(net, n-1, 64)
net = tflearn.batch_normalization(net)
net = tflearn.activation(net, 'relu')
output_layer = tflearn.global_avg_pool(net)
# Regression
net = tflearn.fully_connected(output_layer, 10, activation='softmax')
mom = tflearn.Momentum(0.1, lr_decay=0.1, decay_step=32000, staircase=True)
net = tflearn.regression(net, optimizer=mom,
loss='categorical_crossentropy')
# Training
model = tflearn.DNN(net, checkpoint_path='resnet_v1_152.ckpt',
max_checkpoints=10, tensorboard_verbose=0,
clip_gradients=0.)
model.fit(X, Y, n_epoch=200, validation_set=(testX, testY),
snapshot_epoch=False, snapshot_step=500,
show_metric=True, batch_size=128, shuffle=True,
run_id='resnet_cifar10')
model.save('./resnet_v1_152.ckpt')
#---------------
# now extract the penultimate hidden layer's image feature
img = Image.open(file_path)
img = img.resize((32, 32), Image.ANTIALIAS)
img = np.asarray(img, dtype="float32")
imgs = np.asarray([img])
model_test = tflearn.DNN(output_layer, session = model.session)
model_test.load('resnet_v1_152.ckpt', weights_only = True)
predict_y = model_test.predict(imgs)
print('layer\'s feature'.format(predict_y))
I wish to appear a figure (and certain text) as if they are printed on a page of an open book. Is it possible to transform an jpg image programmatically or in matplotlib to have such an effect?
You can use a background axis along with an open source book image to do something like this,
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax2 = fig.add_axes([0.2, 0.3, 0.25, 0.3])
#Plot page from a book
im = plt.imread("./book_page.jpg")
implot = ax1.imshow(im, origin='lower')
# Plot a graph and set background to transparent
x = np.linspace(0,4.*np.pi,40)
y = np.sin(x)
ax2.plot(x,y,'-ro',alpha=0.5)
ax2.set_ylim([-1.1,1.1])
ax2.patch.set_alpha(0.0)
from matplotlib import rc
rc('text', usetex=True)
margin = im.shape[0]*0.075
ytext = im.shape[1]/2.+10
ax1.text(margin, ytext, "The following text is an example")
ax1.text(margin, 90, "Figure 1. Showing a sine function")
plt.show()
Which looks like this,
where I used the following book image.
UPDATE: Added non-affine transformation based on scikit-image warp example, but with Maxwell distribution. The solution saves the matplotlib line as an image in order to apply a pointwise transform. Mapping for vector graphics may be possible but I think this will be more complicated...
import numpy as np
import matplotlib.pyplot as plt
def maxwellian_transform_image(image):
from skimage.transform import PiecewiseAffineTransform, warp
rows, cols = image.shape[0], image.shape[1]
src_cols = np.linspace(0, cols, 20)
src_rows = np.linspace(0, rows, 10)
src_rows, src_cols = np.meshgrid(src_rows, src_cols)
src = np.dstack([src_cols.flat, src_rows.flat])[0]
# add maxwellian to row coordinates
x = np.linspace(0, 3., src.shape[0])
dst_rows = src[:, 1] + (np.sqrt(2/np.pi)*x**2 * np.exp(-x**2/2)) * 50
dst_cols = src[:, 0]
dst_rows *= 1.5
dst_rows -= 1.0 * 50
dst = np.vstack([dst_cols, dst_rows]).T
tform = PiecewiseAffineTransform()
tform.estimate(src, dst)
out_rows = image.shape[0] - 1.5 * 50
out_cols = cols
out = warp(image, tform, output_shape=(out_rows, out_cols))
return out
#Create the new figure
fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
#Plot page from a book
im = plt.imread("./book_page.jpg")
implot = ax.imshow(im, origin='lower')
# Plot and save graph as image, will need some manipulation of location
temp, at = plt.subplots()
margin = im.shape[0]*0.1
x = np.linspace(margin,im.shape[0]/2.,40)
y = im.shape[1]/3. + 0.1*im.shape[1]*np.sin(12.*np.pi*x/im.shape[0])
at.plot(x,y,'-ro',alpha=0.5)
temp.savefig("lineplot.png",transparent=True)
#Read in plot as an image and apply transform
plot = plt.imread("./lineplot.png")
out = maxwellian_transform_image(plot)
ax.imshow(out, extent=[0,im.shape[1],0,im.shape[0]])
plt.show()
The figure now looks like,